core_info_list_t *core_info_list_new(void) { size_t i; core_info_t *core_info = NULL; core_info_list_t *core_info_list = NULL; settings_t *settings = config_get_ptr(); struct string_list *contents = dir_list_new_special(NULL, DIR_LIST_CORES, NULL); if (!contents) return NULL; core_info_list = (core_info_list_t*)calloc(1, sizeof(*core_info_list)); if (!core_info_list) goto error; core_info = (core_info_t*)calloc(contents->size, sizeof(*core_info)); if (!core_info) goto error; core_info_list->list = core_info; core_info_list->count = contents->size; for (i = 0; i < contents->size; i++) { config_file_t *conf = NULL; char info_path_base[PATH_MAX_LENGTH] = {0}; char info_path[PATH_MAX_LENGTH] = {0}; core_info[i].path = strdup(contents->elems[i].data); if (!core_info[i].path) break; fill_pathname_base(info_path_base, contents->elems[i].data, sizeof(info_path_base)); path_remove_extension(info_path_base); #if defined(RARCH_MOBILE) || (defined(RARCH_CONSOLE) && !defined(PSP)) char *substr = strrchr(info_path_base, '_'); if (substr) *substr = '\0'; #endif strlcat(info_path_base, ".info", sizeof(info_path_base)); fill_pathname_join(info_path, (*settings->libretro_info_path) ? settings->libretro_info_path : settings->libretro_directory, info_path_base, sizeof(info_path)); conf = config_file_new(info_path); if (conf) { unsigned count = 0; config_get_string(conf, "display_name", &core_info[i].display_name); config_get_string(conf, "corename", &core_info[i].core_name); config_get_string(conf, "systemname", &core_info[i].systemname); config_get_string(conf, "manufacturer", &core_info[i].system_manufacturer); config_get_uint(conf, "firmware_count", &count); core_info[i].firmware_count = count; if (config_get_string(conf, "supported_extensions", &core_info[i].supported_extensions) && core_info[i].supported_extensions) core_info[i].supported_extensions_list = string_split(core_info[i].supported_extensions, "|"); if (config_get_string(conf, "authors", &core_info[i].authors) && core_info[i].authors) core_info[i].authors_list = string_split(core_info[i].authors, "|"); if (config_get_string(conf, "permissions", &core_info[i].permissions) && core_info[i].permissions) core_info[i].permissions_list = string_split(core_info[i].permissions, "|"); if (config_get_string(conf, "license", &core_info[i].licenses) && core_info[i].licenses) core_info[i].licenses_list = string_split(core_info[i].licenses, "|"); if (config_get_string(conf, "categories", &core_info[i].categories) && core_info[i].categories) core_info[i].categories_list = string_split(core_info[i].categories, "|"); if (config_get_string(conf, "database", &core_info[i].databases) && core_info[i].databases) core_info[i].databases_list = string_split(core_info[i].databases, "|"); if (config_get_string(conf, "notes", &core_info[i].notes) && core_info[i].notes) core_info[i].note_list = string_split(core_info[i].notes, "|"); config_get_bool(conf, "supports_no_game", &core_info[i].supports_no_game); core_info[i].config_data = conf; } if (!core_info[i].display_name) core_info[i].display_name = strdup(path_basename(core_info[i].path)); } core_info_list_resolve_all_extensions(core_info_list); core_info_list_resolve_all_firmware(core_info_list); dir_list_free(contents); return core_info_list; error: if (contents) dir_list_free(contents); core_info_list_free(core_info_list); return NULL; }
static bool input_autoconfigure_joypad_from_conf_dir( autoconfig_params_t *params) { size_t i; char path[PATH_MAX_LENGTH]; int ret = 0; int index = -1; int current_best = 0; config_file_t *conf = NULL; struct string_list *list = NULL; settings_t *settings = config_get_ptr(); if (!settings) return false; fill_pathname_join(path, settings->directory.autoconfig, settings->input.joypad_driver, sizeof(path)); list = dir_list_new_special(path, DIR_LIST_AUTOCONFIG, "cfg"); if (!list || !list->size) list = dir_list_new_special(settings->directory.autoconfig, DIR_LIST_AUTOCONFIG, "cfg"); if(!list) return false; RARCH_LOG("Autodetect: %d profiles found\n", list->size); for (i = 0; i < list->size; i++) { conf = config_file_new(list->elems[i].data); ret = input_try_autoconfigure_joypad_from_conf(conf, params); if(ret >= current_best) { index = i; current_best = ret; } config_file_free(conf); } if(index >= 0 && current_best > 0) { conf = config_file_new(list->elems[index].data); if (conf) { char conf_path[PATH_MAX_LENGTH]; config_get_config_path(conf, conf_path, sizeof(conf_path)); RARCH_LOG("Autodetect: selected configuration: %s\n", conf_path); input_autoconfigure_joypad_add(conf, params); config_file_free(conf); ret = 1; } } else ret = 0; string_list_free(list); if (ret == 0) return false; return true; }
static bool ffmpeg_init_config(struct ff_config_param *params, const char *config) { struct config_file_entry entry; char pix_fmt[64] = {0}; params->out_pix_fmt = PIX_FMT_NONE; params->scale_factor = 1; params->threads = 1; params->frame_drop_ratio = 1; if (!config) return true; params->conf = config_file_new(config); if (!params->conf) { RARCH_ERR("Failed to load FFmpeg config \"%s\".\n", config); return false; } config_get_array(params->conf, "vcodec", params->vcodec, sizeof(params->vcodec)); config_get_array(params->conf, "acodec", params->acodec, sizeof(params->acodec)); config_get_array(params->conf, "format", params->format, sizeof(params->format)); config_get_uint(params->conf, "threads", ¶ms->threads); if (!config_get_uint(params->conf, "frame_drop_ratio", ¶ms->frame_drop_ratio) || !params->frame_drop_ratio) params->frame_drop_ratio = 1; if (!config_get_bool(params->conf, "audio_enable", ¶ms->audio_enable)) params->audio_enable = true; config_get_uint(params->conf, "sample_rate", ¶ms->sample_rate); config_get_uint(params->conf, "scale_factor", ¶ms->scale_factor); params->audio_qscale = config_get_int(params->conf, "audio_global_quality", ¶ms->audio_global_quality); config_get_int(params->conf, "audio_bit_rate", ¶ms->audio_bit_rate); params->video_qscale = config_get_int(params->conf, "video_global_quality", ¶ms->video_global_quality); config_get_int(params->conf, "video_bit_rate", ¶ms->video_bit_rate); if (config_get_array(params->conf, "pix_fmt", pix_fmt, sizeof(pix_fmt))) { params->out_pix_fmt = av_get_pix_fmt(pix_fmt); if (params->out_pix_fmt == PIX_FMT_NONE) { RARCH_ERR("Cannot find pix_fmt \"%s\".\n", pix_fmt); return false; } } if (!config_get_entry_list_head(params->conf, &entry)) return true; do { if (strstr(entry.key, "video_") == entry.key) { const char *key = entry.key + strlen("video_"); av_dict_set(¶ms->video_opts, key, entry.value, 0); } else if (strstr(entry.key, "audio_") == entry.key) { const char *key = entry.key + strlen("audio_"); av_dict_set(¶ms->audio_opts, key, entry.value, 0); } } while (config_get_entry_list_next(&entry)); return true; }
void core_info_get_name(const char *path, char *s, size_t len) { size_t i; core_info_t *core_info = NULL; core_info_list_t *core_info_list = NULL; settings_t *settings = config_get_ptr(); struct string_list *contents = dir_list_new_special(NULL, DIR_LIST_CORES, NULL); if (!contents) return; core_info_list = (core_info_list_t*)calloc(1, sizeof(*core_info_list)); if (!core_info_list) goto error; core_info = (core_info_t*)calloc(contents->size, sizeof(*core_info)); if (!core_info) goto error; core_info_list->list = core_info; core_info_list->count = contents->size; for (i = 0; i < contents->size; i++) { config_file_t *conf = NULL; char info_path_base[PATH_MAX_LENGTH] = {0}; char info_path[PATH_MAX_LENGTH] = {0}; core_info[i].path = strdup(contents->elems[i].data); if (!core_info[i].path) break; if (strcmp(core_info[i].path, path) != 0) continue; fill_pathname_base(info_path_base, contents->elems[i].data, sizeof(info_path_base)); path_remove_extension(info_path_base); #if defined(RARCH_MOBILE) || (defined(RARCH_CONSOLE) && !defined(PSP)) char *substr = strrchr(info_path_base, '_'); if (substr) *substr = '\0'; #endif strlcat(info_path_base, ".info", sizeof(info_path_base)); fill_pathname_join(info_path, (*settings->libretro_info_path) ? settings->libretro_info_path : settings->libretro_directory, info_path_base, sizeof(info_path)); conf = config_file_new(info_path); if (conf) { config_get_string(conf, "corename", &core_info[i].core_name); core_info[i].config_data = (void*)conf; } strlcpy(s, core_info[i].core_name, len); } error: if (contents) dir_list_free(contents); contents = NULL; core_info_list_free(core_info_list); }
static config_file_t *open_default_config_file(void) { config_file_t *conf = NULL; #if defined(_WIN32) && !defined(_XBOX) char conf_path[PATH_MAX]; char app_path[PATH_MAX]; fill_pathname_application_path(app_path, sizeof(app_path)); fill_pathname_resolve_relative(conf_path, app_path, "retroarch.cfg", sizeof(conf_path)); conf = config_file_new(conf_path); if (!conf) { const char *appdata = getenv("APPDATA"); if (appdata) { fill_pathname_join(conf_path, appdata, "retroarch.cfg", sizeof(conf_path)); conf = config_file_new(conf_path); } } // Try to create a new config file. if (!conf) { conf = config_file_new(NULL); bool saved = false; if (conf) // Since this is a clean config file, we can safely use config_save_on_exit. { fill_pathname_resolve_relative(conf_path, app_path, "retroarch.cfg", sizeof(conf_path)); config_set_bool(conf, "config_save_on_exit", true); saved = config_file_write(conf, conf_path); } if (saved) RARCH_WARN("Created new config file in: \"%s\".\n", conf_path); // WARN here to make sure user has a good chance of seeing it. else { RARCH_ERR("Failed to create new config file in: \"%s\".\n", conf_path); config_file_free(conf); conf = NULL; } } if (conf) strlcpy(g_extern.config_path, conf_path, sizeof(g_extern.config_path)); #elif !defined(__CELLOS_LV2__) && !defined(_XBOX) char conf_path[PATH_MAX]; const char *xdg = getenv("XDG_CONFIG_HOME"); const char *home = getenv("HOME"); // XDG_CONFIG_HOME falls back to $HOME/.config. if (xdg) fill_pathname_join(conf_path, xdg, "retroarch/retroarch.cfg", sizeof(conf_path)); else if (home) fill_pathname_join(conf_path, home, ".config/retroarch/retroarch.cfg", sizeof(conf_path)); if (xdg || home) { RARCH_LOG("Looking for config in: \"%s\".\n", conf_path); conf = config_file_new(conf_path); } // Fallback to $HOME/.retroarch.cfg. if (!conf && home) { fill_pathname_join(conf_path, home, ".retroarch.cfg", sizeof(conf_path)); RARCH_LOG("Looking for config in: \"%s\".\n", conf_path); conf = config_file_new(conf_path); } // Try to create a new config file. if (!conf && (home || xdg)) { // XDG_CONFIG_HOME falls back to $HOME/.config. if (xdg) fill_pathname_join(conf_path, xdg, "retroarch/retroarch.cfg", sizeof(conf_path)); else if (home) fill_pathname_join(conf_path, home, ".config/retroarch/retroarch.cfg", sizeof(conf_path)); char basedir[PATH_MAX]; fill_pathname_basedir(basedir, conf_path, sizeof(basedir)); if (path_mkdir(basedir)) { #ifndef GLOBAL_CONFIG_DIR #define GLOBAL_CONFIG_DIR "/etc" #endif char skeleton_conf[PATH_MAX]; fill_pathname_join(skeleton_conf, GLOBAL_CONFIG_DIR, "retroarch.cfg", sizeof(skeleton_conf)); conf = config_file_new(skeleton_conf); if (conf) RARCH_WARN("Using skeleton config \"%s\" as base for a new config file.\n", skeleton_conf); else conf = config_file_new(NULL); bool saved = false; if (conf) { config_set_bool(conf, "config_save_on_exit", true); // Since this is a clean config file, we can safely use config_save_on_exit. saved = config_file_write(conf, conf_path); } if (saved) RARCH_WARN("Created new config file in: \"%s\".\n", conf_path); // WARN here to make sure user has a good chance of seeing it. else { RARCH_ERR("Failed to create new config file in: \"%s\".\n", conf_path); config_file_free(conf); conf = NULL; } } } if (conf) strlcpy(g_extern.config_path, conf_path, sizeof(g_extern.config_path)); #endif return conf; }
bool config_load_file(const char *path) { config_file_t *conf = NULL; if (path) { conf = config_file_new(path); if (!conf) return false; } else conf = open_default_config_file(); if (conf == NULL) return true; char *save; char tmp_append_path[PATH_MAX]; // Don't destroy append_config_path. strlcpy(tmp_append_path, g_extern.append_config_path, sizeof(tmp_append_path)); const char *extra_path = strtok_r(tmp_append_path, ",", &save); while (extra_path) { RARCH_LOG("Appending config \"%s\"\n", extra_path); bool ret = config_append_file(conf, extra_path); if (!ret) RARCH_ERR("Failed to append config \"%s\"\n", extra_path); extra_path = strtok_r(NULL, ";", &save); } if (g_extern.verbose) { RARCH_LOG_OUTPUT("=== Config ===\n"); config_file_dump_all(conf, stderr); RARCH_LOG_OUTPUT("=== Config end ===\n"); } char tmp_str[PATH_MAX]; CONFIG_GET_FLOAT(video.xscale, "video_xscale"); CONFIG_GET_FLOAT(video.yscale, "video_yscale"); CONFIG_GET_INT(video.fullscreen_x, "video_fullscreen_x"); CONFIG_GET_INT(video.fullscreen_y, "video_fullscreen_y"); if (!g_extern.force_fullscreen) CONFIG_GET_BOOL(video.fullscreen, "video_fullscreen"); CONFIG_GET_BOOL(video.windowed_fullscreen, "video_windowed_fullscreen"); CONFIG_GET_INT(video.monitor_index, "video_monitor_index"); CONFIG_GET_BOOL(video.disable_composition, "video_disable_composition"); CONFIG_GET_BOOL(video.vsync, "video_vsync"); CONFIG_GET_BOOL(video.hard_sync, "video_hard_sync"); CONFIG_GET_INT(video.hard_sync_frames, "video_hard_sync_frames"); if (g_settings.video.hard_sync_frames > 3) g_settings.video.hard_sync_frames = 3; CONFIG_GET_BOOL(video.black_frame_insertion, "video_black_frame_insertion"); CONFIG_GET_INT(video.swap_interval, "video_swap_interval"); g_settings.video.swap_interval = max(g_settings.video.swap_interval, 1); g_settings.video.swap_interval = min(g_settings.video.swap_interval, 4); CONFIG_GET_BOOL(video.threaded, "video_threaded"); CONFIG_GET_BOOL(video.smooth, "video_smooth"); CONFIG_GET_BOOL(video.force_aspect, "video_force_aspect"); CONFIG_GET_BOOL(video.scale_integer, "video_scale_integer"); CONFIG_GET_BOOL(video.crop_overscan, "video_crop_overscan"); CONFIG_GET_FLOAT(video.aspect_ratio, "video_aspect_ratio"); CONFIG_GET_INT(video.aspect_ratio_idx, "aspect_ratio_index"); CONFIG_GET_BOOL(video.aspect_ratio_auto, "video_aspect_ratio_auto"); CONFIG_GET_FLOAT(video.refresh_rate, "video_refresh_rate"); CONFIG_GET_PATH(video.shader_path, "video_shader"); CONFIG_GET_BOOL(video.shader_enable, "video_shader_enable"); CONFIG_GET_BOOL(video.allow_rotate, "video_allow_rotate"); CONFIG_GET_PATH(video.font_path, "video_font_path"); CONFIG_GET_FLOAT(video.font_size, "video_font_size"); CONFIG_GET_BOOL(video.font_enable, "video_font_enable"); CONFIG_GET_BOOL(video.font_scale, "video_font_scale"); CONFIG_GET_FLOAT(video.msg_pos_x, "video_message_pos_x"); CONFIG_GET_FLOAT(video.msg_pos_y, "video_message_pos_y"); CONFIG_GET_INT(video.rotation, "video_rotation"); #ifdef RARCH_CONSOLE /* TODO - will be refactored later to make it more clean - it's more * important that it works for consoles right now */ CONFIG_GET_BOOL_EXTERN(console.screen.gamma_correction, "gamma_correction"); bool msg_enable = false; bool triple_buffering_enable = false; bool custom_bgm_enable = false; bool flicker_filter_enable = false; bool soft_filter_enable = false; #ifdef HAVE_RMENU if (config_get_path(conf, "menu_texture_path", tmp_str, sizeof(tmp_str))) strlcpy(g_extern.menu_texture_path, tmp_str, sizeof(g_extern.menu_texture_path)); #endif if (config_get_bool(conf, "info_msg_enable", &msg_enable)) { if (msg_enable) g_extern.lifecycle_mode_state |= (1ULL << MODE_INFO_DRAW); else g_extern.lifecycle_mode_state &= ~(1ULL << MODE_INFO_DRAW); } if (config_get_bool(conf, "triple_buffering_enable", &triple_buffering_enable)) { if (triple_buffering_enable) g_extern.lifecycle_mode_state |= (1ULL << MODE_VIDEO_TRIPLE_BUFFERING_ENABLE); else g_extern.lifecycle_mode_state &= ~(1ULL << MODE_VIDEO_TRIPLE_BUFFERING_ENABLE); } if (config_get_bool(conf, "custom_bgm_enable", &custom_bgm_enable)) { if (custom_bgm_enable) g_extern.lifecycle_mode_state |= (1ULL << MODE_AUDIO_CUSTOM_BGM_ENABLE); else g_extern.lifecycle_mode_state &= ~(1ULL << MODE_AUDIO_CUSTOM_BGM_ENABLE); } if (config_get_bool(conf, "flicker_filter_enable", &flicker_filter_enable)) { if (flicker_filter_enable) g_extern.lifecycle_mode_state |= (1ULL << MODE_VIDEO_FLICKER_FILTER_ENABLE); else g_extern.lifecycle_mode_state &= ~(1ULL << MODE_VIDEO_FLICKER_FILTER_ENABLE); } if (config_get_bool(conf, "soft_filter_enable", &soft_filter_enable)) { if (soft_filter_enable) g_extern.lifecycle_mode_state |= (1ULL << MODE_VIDEO_SOFT_FILTER_ENABLE); else g_extern.lifecycle_mode_state &= ~(1ULL << MODE_VIDEO_SOFT_FILTER_ENABLE); } CONFIG_GET_INT_EXTERN(console.screen.flicker_filter_index, "flicker_filter_index"); CONFIG_GET_INT_EXTERN(console.screen.soft_filter_index, "soft_filter_index"); #ifdef _XBOX1 CONFIG_GET_INT_EXTERN(console.sound.volume_level, "sound_volume_level"); #endif CONFIG_GET_INT_EXTERN(console.screen.resolutions.current.id, "current_resolution_id"); CONFIG_GET_INT_EXTERN(state_slot, "state_slot"); CONFIG_GET_INT_EXTERN(audio_data.mute, "audio_mute"); CONFIG_GET_INT_EXTERN(console.sound.mode, "sound_mode"); #endif CONFIG_GET_INT_EXTERN(console.screen.viewports.custom_vp.x, "custom_viewport_x"); CONFIG_GET_INT_EXTERN(console.screen.viewports.custom_vp.y, "custom_viewport_y"); CONFIG_GET_INT_EXTERN(console.screen.viewports.custom_vp.width, "custom_viewport_width"); CONFIG_GET_INT_EXTERN(console.screen.viewports.custom_vp.height, "custom_viewport_height"); unsigned msg_color = 0; if (config_get_hex(conf, "video_message_color", &msg_color)) { g_settings.video.msg_color_r = ((msg_color >> 16) & 0xff) / 255.0f; g_settings.video.msg_color_g = ((msg_color >> 8) & 0xff) / 255.0f; g_settings.video.msg_color_b = ((msg_color >> 0) & 0xff) / 255.0f; }
int secure_init_options () { struct t_config_section *ptr_section; secure_config_file = config_file_new (NULL, SECURE_CONFIG_NAME, &secure_reload_cb, NULL); if (!secure_config_file) return 0; /* crypt */ ptr_section = config_file_new_section (secure_config_file, "crypt", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (!ptr_section) { config_file_free (secure_config_file); return 0; } secure_config_crypt_cipher = config_file_new_option ( secure_config_file, ptr_section, "cipher", "integer", N_("cipher used to crypt data (the number after algorithm is the size " "of the key in bits)"), "aes128|aes192|aes256", 0, 0, "aes256", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); secure_config_crypt_hash_algo = config_file_new_option ( secure_config_file, ptr_section, "hash_algo", "integer", N_("hash algorithm used to check the decrypted data"), "sha224|sha256|sha384|sha512", 0, 0, "sha256", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); secure_config_crypt_passphrase_file = config_file_new_option ( secure_config_file, ptr_section, "passphrase_file", "string", N_("path to a file containing the passphrase to encrypt/decrypt secured " "data; this option is used only when reading file sec.conf; only " "first line of file is used; this file is used only if the " "environment variable \"WEECHAT_PASSPHRASE\" is not set (the " "environment variable has higher priority); security note: it is " "recommended to keep this file readable only by you and store it " "outside WeeChat home (for example in your home); example: " "\"~/.weechat-passphrase\""), NULL, 0, 0, "", NULL, 0, &secure_check_crypt_passphrase_file, NULL, NULL, NULL, NULL, NULL); secure_config_crypt_salt = config_file_new_option ( secure_config_file, ptr_section, "salt", "boolean", N_("use salt when generating key used in encryption (recommended for " "maximum security); when enabled, the content of crypted data in " "file sec.conf will be different on each write of the file; if you " "put the file sec.conf in a version control system, then you " "can turn off this option to have always same content in file"), NULL, 0, 0, "on", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); /* data */ ptr_section = config_file_new_section (secure_config_file, "data", 0, 0, &secure_data_read_cb, NULL, &secure_data_write_cb, NULL, &secure_data_write_cb, NULL, NULL, NULL, NULL, NULL); if (!ptr_section) { config_file_free (secure_config_file); return 0; } return 1; }
static bool load_preset(cg_shader_data_t *cg, const char *path) { unsigned i; config_file_t *conf = NULL; if (!load_stock(cg)) return false; RARCH_LOG("Loading Cg meta-shader: %s\n", path); conf = config_file_new(path); if (!conf) { RARCH_ERR("Failed to load preset.\n"); return false; } cg->shader = (struct video_shader*)calloc(1, sizeof(*cg->shader)); if (!cg->shader) { config_file_free(conf); return false; } if (!video_shader_read_conf_cgp(conf, cg->shader)) { RARCH_ERR("Failed to parse CGP file.\n"); config_file_free(conf); return false; } video_shader_resolve_relative(cg->shader, path); video_shader_resolve_parameters(conf, cg->shader); config_file_free(conf); if (cg->shader->passes > GFX_MAX_SHADERS - 3) { RARCH_WARN("Too many shaders ... Capping shader amount to %d.\n", GFX_MAX_SHADERS - 3); cg->shader->passes = GFX_MAX_SHADERS - 3; } for (i = 0; i < cg->shader->passes; i++) if (*cg->shader->pass[i].alias) snprintf(cg->cg_alias_define[i], sizeof(cg->cg_alias_define[i]), "-D%s_ALIAS", cg->shader->pass[i].alias); for (i = 0; i < cg->shader->passes; i++) { if (!load_shader(cg, i)) { RARCH_ERR("Failed to load shaders ...\n"); return false; } } if (!gl_load_luts(cg->shader, cg->lut_textures)) { RARCH_ERR("Failed to load lookup textures ...\n"); return false; } if (!gl_cg_load_imports(cg)) { RARCH_ERR("Failed to load imports ...\n"); return false; } return true; }
bool input_overlay_load_overlays(input_overlay_t *ol) { unsigned i; config_file_t *conf = NULL; if (!ol) return false; conf = config_file_new(ol->overlay_path); if (!conf) { RARCH_ERR("Failed to load config file: %s.\n", ol->overlay_path); return false; } if (!config_get_uint(conf, "overlays", &ol->config.overlays.size)) { RARCH_ERR("overlays variable not defined in config.\n"); goto error; } if (!ol->config.overlays.size) goto error; ol->overlays = (struct overlay*)calloc( ol->config.overlays.size, sizeof(*ol->overlays)); if (!ol->overlays) goto error; ol->size = ol->config.overlays.size; ol->pos = 0; ol->resolve_pos = 0; for (i = 0; i < ol->size; i++) { char conf_key[64]; char overlay_full_screen_key[64]; struct overlay *overlay = &ol->overlays[i]; if (!overlay) continue; snprintf(overlay->config.descs.key, sizeof(overlay->config.descs.key), "overlay%u_descs", i); if (!config_get_uint(conf, overlay->config.descs.key, &overlay->config.descs.size)) { RARCH_ERR("[Overlay]: Failed to read number of descs from config key: %s.\n", overlay->config.descs.key); goto error; } overlay->descs = (struct overlay_desc*) calloc(overlay->config.descs.size, sizeof(*overlay->descs)); if (!overlay->descs) { RARCH_ERR("[Overlay]: Failed to allocate descs.\n"); goto error; } overlay->size = overlay->config.descs.size; snprintf(overlay_full_screen_key, sizeof(overlay_full_screen_key), "overlay%u_full_screen", i); overlay->full_screen = false; config_get_bool(conf, overlay_full_screen_key, &overlay->full_screen); overlay->config.normalized = false; overlay->config.alpha_mod = 1.0f; overlay->config.range_mod = 1.0f; snprintf(conf_key, sizeof(conf_key), "overlay%u_normalized", i); config_get_bool(conf, conf_key, &overlay->config.normalized); snprintf(conf_key, sizeof(conf_key), "overlay%u_alpha_mod", i); config_get_float(conf, conf_key, &overlay->config.alpha_mod); snprintf(conf_key, sizeof(conf_key), "overlay%u_range_mod", i); config_get_float(conf, conf_key, &overlay->config.range_mod); /* Precache load image array for simplicity. */ overlay->load_images = (struct texture_image*) calloc(1 + overlay->size, sizeof(struct texture_image)); if (!overlay->load_images) { RARCH_ERR("[Overlay]: Failed to allocate load_images.\n"); goto error; } snprintf(overlay->config.paths.key, sizeof(overlay->config.paths.key), "overlay%u_overlay", i); config_get_path(conf, overlay->config.paths.key, overlay->config.paths.path, sizeof(overlay->config.paths.path)); if (overlay->config.paths.path[0] != '\0') { char overlay_resolved_path[PATH_MAX_LENGTH]; struct texture_image img = {0}; fill_pathname_resolve_relative(overlay_resolved_path, ol->overlay_path, overlay->config.paths.path, sizeof(overlay_resolved_path)); if (!texture_image_load(&img, overlay_resolved_path)) { RARCH_ERR("[Overlay]: Failed to load image: %s.\n", overlay_resolved_path); ol->loading_status = OVERLAY_IMAGE_TRANSFER_ERROR; goto error; } overlay->image = img; } snprintf(overlay->config.names.key, sizeof(overlay->config.names.key), "overlay%u_name", i); config_get_array(conf, overlay->config.names.key, overlay->name, sizeof(overlay->name)); /* By default, we stretch the overlay out in full. */ overlay->x = overlay->y = 0.0f; overlay->w = overlay->h = 1.0f; snprintf(overlay->config.rect.key, sizeof(overlay->config.rect.key), "overlay%u_rect", i); if (config_get_array(conf, overlay->config.rect.key, overlay->config.rect.array, sizeof(overlay->config.rect.array))) { struct string_list *list = string_split(overlay->config.rect.array, ", "); if (!list || list->size < 4) { RARCH_ERR("[Overlay]: Failed to split rect \"%s\" into at least four tokens.\n", overlay->config.rect.array); string_list_free(list); goto error; } overlay->x = (float)strtod(list->elems[0].data, NULL); overlay->y = (float)strtod(list->elems[1].data, NULL); overlay->w = (float)strtod(list->elems[2].data, NULL); overlay->h = (float)strtod(list->elems[3].data, NULL); string_list_free(list); } /* Assume for now that scaling center is in the middle. * TODO: Make this configurable. */ overlay->block_scale = false; overlay->center_x = overlay->x + 0.5f * overlay->w; overlay->center_y = overlay->y + 0.5f * overlay->h; } ol->state = OVERLAY_STATUS_DEFERRED_LOADING; config_file_free(conf); return true; error: config_file_free(conf); ol->state = OVERLAY_STATUS_DEFERRED_ERROR; return false; }
int menu_set_settings(unsigned setting, unsigned action) { unsigned port = rgui->current_pad; switch (setting) { case RGUI_START_SCREEN: if (action == RGUI_ACTION_OK) rgui_list_push(rgui->menu_stack, "", RGUI_START_SCREEN, 0); break; case RGUI_SETTINGS_REWIND_ENABLE: if (action == RGUI_ACTION_OK || action == RGUI_ACTION_LEFT || action == RGUI_ACTION_RIGHT) { settings_set(1ULL << S_REWIND); if (g_settings.rewind_enable) rarch_init_rewind(); else rarch_deinit_rewind(); } else if (action == RGUI_ACTION_START) { g_settings.rewind_enable = false; rarch_deinit_rewind(); } break; #ifdef HAVE_SCREENSHOTS case RGUI_SETTINGS_GPU_SCREENSHOT: if (action == RGUI_ACTION_OK || action == RGUI_ACTION_LEFT || action == RGUI_ACTION_RIGHT) g_settings.video.gpu_screenshot = !g_settings.video.gpu_screenshot; else if (action == RGUI_ACTION_START) g_settings.video.gpu_screenshot = true; break; #endif case RGUI_SETTINGS_REWIND_GRANULARITY: if (action == RGUI_ACTION_OK || action == RGUI_ACTION_RIGHT) settings_set(1ULL << S_REWIND_GRANULARITY_INCREMENT); else if (action == RGUI_ACTION_LEFT) settings_set(1ULL << S_REWIND_GRANULARITY_DECREMENT); else if (action == RGUI_ACTION_START) settings_set(1ULL << S_DEF_REWIND_GRANULARITY); break; case RGUI_SETTINGS_CONFIG_SAVE_ON_EXIT: if (action == RGUI_ACTION_OK || action == RGUI_ACTION_RIGHT || action == RGUI_ACTION_LEFT) { g_extern.config_save_on_exit = !g_extern.config_save_on_exit; } else if (action == RGUI_ACTION_START) g_extern.config_save_on_exit = true; break; #if defined(HAVE_THREADS) && !defined(RARCH_CONSOLE) case RGUI_SETTINGS_SRAM_AUTOSAVE: if (action == RGUI_ACTION_OK || action == RGUI_ACTION_RIGHT || action == RGUI_ACTION_LEFT) { rarch_deinit_autosave(); g_settings.autosave_interval = (!g_settings.autosave_interval) * 10; if (g_settings.autosave_interval) rarch_init_autosave(); } else if (action == RGUI_ACTION_START) { rarch_deinit_autosave(); g_settings.autosave_interval = 0; } break; #endif case RGUI_SETTINGS_SAVESTATE_SAVE: case RGUI_SETTINGS_SAVESTATE_LOAD: if (action == RGUI_ACTION_OK) { if (setting == RGUI_SETTINGS_SAVESTATE_SAVE) rarch_save_state(); else rarch_load_state(); g_extern.lifecycle_mode_state |= (1ULL << MODE_GAME); return -1; } else if (action == RGUI_ACTION_START) settings_set(1ULL << S_DEF_SAVE_STATE); else if (action == RGUI_ACTION_LEFT) settings_set(1ULL << S_SAVESTATE_DECREMENT); else if (action == RGUI_ACTION_RIGHT) settings_set(1ULL << S_SAVESTATE_INCREMENT); break; #ifdef HAVE_SCREENSHOTS case RGUI_SETTINGS_SCREENSHOT: if (action == RGUI_ACTION_OK) rarch_take_screenshot(); break; #endif case RGUI_SETTINGS_RESTART_GAME: if (action == RGUI_ACTION_OK) { rarch_game_reset(); g_extern.lifecycle_mode_state |= (1ULL << MODE_GAME); return -1; } break; case RGUI_SETTINGS_AUDIO_MUTE: if (action == RGUI_ACTION_START) settings_set(1ULL << S_DEF_AUDIO_MUTE); else settings_set(1ULL << S_AUDIO_MUTE); break; case RGUI_SETTINGS_AUDIO_CONTROL_RATE_DELTA: if (action == RGUI_ACTION_START) settings_set(1ULL << S_DEF_AUDIO_CONTROL_RATE); else if (action == RGUI_ACTION_LEFT) settings_set(1ULL << S_AUDIO_CONTROL_RATE_DECREMENT); else if (action == RGUI_ACTION_RIGHT) settings_set(1ULL << S_AUDIO_CONTROL_RATE_INCREMENT); break; case RGUI_SETTINGS_DEBUG_TEXT: if (action == RGUI_ACTION_START) g_settings.fps_show = false; else if (action == RGUI_ACTION_LEFT || action == RGUI_ACTION_RIGHT) g_settings.fps_show = !g_settings.fps_show; break; case RGUI_SETTINGS_DISK_INDEX: { const struct retro_disk_control_callback *control = &g_extern.system.disk_control; unsigned num_disks = control->get_num_images(); unsigned current = control->get_image_index(); int step = 0; if (action == RGUI_ACTION_RIGHT || action == RGUI_ACTION_OK) step = 1; else if (action == RGUI_ACTION_LEFT) step = -1; if (step) { unsigned next_index = (current + num_disks + 1 + step) % (num_disks + 1); rarch_disk_control_set_eject(true, false); rarch_disk_control_set_index(next_index); rarch_disk_control_set_eject(false, false); } break; } case RGUI_SETTINGS_RESTART_EMULATOR: if (action == RGUI_ACTION_OK) { #if defined(GEKKO) && defined(HW_RVL) fill_pathname_join(g_extern.fullpath, default_paths.core_dir, SALAMANDER_FILE, sizeof(g_extern.fullpath)); #endif g_extern.lifecycle_mode_state &= ~(1ULL << MODE_GAME); g_extern.lifecycle_mode_state |= (1ULL << MODE_EXITSPAWN); return -1; } break; case RGUI_SETTINGS_RESUME_GAME: if (action == RGUI_ACTION_OK) { g_extern.lifecycle_mode_state |= (1ULL << MODE_GAME); return -1; } break; case RGUI_SETTINGS_QUIT_RARCH: if (action == RGUI_ACTION_OK) { g_extern.lifecycle_mode_state &= ~(1ULL << MODE_GAME); return -1; } break; case RGUI_SETTINGS_SAVE_CONFIG: if (action == RGUI_ACTION_OK) menu_save_new_config(); break; #ifdef HAVE_OVERLAY case RGUI_SETTINGS_OVERLAY_PRESET: switch (action) { case RGUI_ACTION_OK: rgui_list_push(rgui->menu_stack, g_extern.overlay_dir, setting, rgui->selection_ptr); rgui->selection_ptr = 0; rgui->need_refresh = true; break; #ifndef __QNX__ // FIXME: Why ifndef QNX? case RGUI_ACTION_START: if (driver.overlay) input_overlay_free(driver.overlay); driver.overlay = NULL; *g_settings.input.overlay = '\0'; break; #endif default: break; } break; case RGUI_SETTINGS_OVERLAY_OPACITY: { bool changed = true; switch (action) { case RGUI_ACTION_LEFT: settings_set(1ULL << S_INPUT_OVERLAY_OPACITY_DECREMENT); break; case RGUI_ACTION_RIGHT: case RGUI_ACTION_OK: settings_set(1ULL << S_INPUT_OVERLAY_OPACITY_INCREMENT); break; case RGUI_ACTION_START: settings_set(1ULL << S_DEF_INPUT_OVERLAY_OPACITY); break; default: changed = false; break; } if (changed && driver.overlay) input_overlay_set_alpha_mod(driver.overlay, g_settings.input.overlay_opacity); break; } case RGUI_SETTINGS_OVERLAY_SCALE: { bool changed = true; switch (action) { case RGUI_ACTION_LEFT: settings_set(1ULL << S_INPUT_OVERLAY_SCALE_DECREMENT); break; case RGUI_ACTION_RIGHT: case RGUI_ACTION_OK: settings_set(1ULL << S_INPUT_OVERLAY_SCALE_INCREMENT); break; case RGUI_ACTION_START: settings_set(1ULL << S_DEF_INPUT_OVERLAY_SCALE); break; default: changed = false; break; } if (changed && driver.overlay) input_overlay_set_scale_factor(driver.overlay, g_settings.input.overlay_scale); break; } #endif // controllers case RGUI_SETTINGS_BIND_PLAYER: if (action == RGUI_ACTION_START) rgui->current_pad = 0; else if (action == RGUI_ACTION_LEFT) { if (rgui->current_pad != 0) rgui->current_pad--; } else if (action == RGUI_ACTION_RIGHT) { if (rgui->current_pad < MAX_PLAYERS - 1) rgui->current_pad++; } #ifdef HAVE_RGUI if (port != rgui->current_pad) rgui->need_refresh = true; #endif port = rgui->current_pad; break; case RGUI_SETTINGS_BIND_DEVICE: // If set_keybinds is supported, we do it more fancy, and scroll through // a list of supported devices directly. if (driver.input->set_keybinds) { g_settings.input.device[port] += DEVICE_LAST; if (action == RGUI_ACTION_START) g_settings.input.device[port] = 0; else if (action == RGUI_ACTION_LEFT) g_settings.input.device[port]--; else if (action == RGUI_ACTION_RIGHT) g_settings.input.device[port]++; // DEVICE_LAST can be 0, avoid modulo. if (g_settings.input.device[port] >= DEVICE_LAST) g_settings.input.device[port] -= DEVICE_LAST; unsigned keybind_action = (1ULL << KEYBINDS_ACTION_SET_DEFAULT_BINDS); driver.input->set_keybinds(driver.input_data, g_settings.input.device[port], port, 0, keybind_action); } else { // When only straight g_settings.input.joypad_map[] style // mapping is supported. int *p = &g_settings.input.joypad_map[port]; if (action == RGUI_ACTION_START) *p = port; else if (action == RGUI_ACTION_LEFT) (*p)--; else if (action == RGUI_ACTION_RIGHT) (*p)++; if (*p < -1) *p = -1; else if (*p >= MAX_PLAYERS) *p = MAX_PLAYERS - 1; } break; case RGUI_SETTINGS_BIND_DEVICE_TYPE: { static const unsigned device_types[] = { RETRO_DEVICE_NONE, RETRO_DEVICE_JOYPAD, RETRO_DEVICE_ANALOG, RETRO_DEVICE_MOUSE, RETRO_DEVICE_JOYPAD_MULTITAP, RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE, RETRO_DEVICE_LIGHTGUN_JUSTIFIER, RETRO_DEVICE_LIGHTGUN_JUSTIFIERS, }; unsigned current_device, current_index, i; current_device = g_settings.input.libretro_device[port]; current_index = 0; for (i = 0; i < ARRAY_SIZE(device_types); i++) { if (current_device == device_types[i]) { current_index = i; break; } } bool updated = true; switch (action) { case RGUI_ACTION_START: current_device = RETRO_DEVICE_JOYPAD; break; case RGUI_ACTION_LEFT: current_device = device_types[(current_index + ARRAY_SIZE(device_types) - 1) % ARRAY_SIZE(device_types)]; break; case RGUI_ACTION_RIGHT: case RGUI_ACTION_OK: current_device = device_types[(current_index + 1) % ARRAY_SIZE(device_types)]; break; default: updated = false; } if (updated) { g_settings.input.libretro_device[port] = current_device; pretro_set_controller_port_device(port, current_device); } break; } case RGUI_SETTINGS_CUSTOM_BIND_ALL: if (action == RGUI_ACTION_OK) { rgui->binds.target = &g_settings.input.binds[port][0]; rgui->binds.begin = RGUI_SETTINGS_BIND_BEGIN; rgui->binds.last = RGUI_SETTINGS_BIND_LAST; rgui_list_push(rgui->menu_stack, "", RGUI_SETTINGS_CUSTOM_BIND, rgui->selection_ptr); menu_poll_bind_get_rested_axes(&rgui->binds); menu_poll_bind_state(&rgui->binds); } break; case RGUI_SETTINGS_CUSTOM_BIND_DEFAULT_ALL: if (action == RGUI_ACTION_OK) { unsigned i; struct retro_keybind *target = &g_settings.input.binds[port][0]; rgui->binds.begin = RGUI_SETTINGS_BIND_BEGIN; rgui->binds.last = RGUI_SETTINGS_BIND_LAST; for (i = RGUI_SETTINGS_BIND_BEGIN; i <= RGUI_SETTINGS_BIND_LAST; i++, target++) { target->joykey = NO_BTN; target->joyaxis = AXIS_NONE; } } break; case RGUI_SETTINGS_BIND_UP: case RGUI_SETTINGS_BIND_DOWN: case RGUI_SETTINGS_BIND_LEFT: case RGUI_SETTINGS_BIND_RIGHT: case RGUI_SETTINGS_BIND_A: case RGUI_SETTINGS_BIND_B: case RGUI_SETTINGS_BIND_X: case RGUI_SETTINGS_BIND_Y: case RGUI_SETTINGS_BIND_START: case RGUI_SETTINGS_BIND_SELECT: case RGUI_SETTINGS_BIND_L: case RGUI_SETTINGS_BIND_R: case RGUI_SETTINGS_BIND_L2: case RGUI_SETTINGS_BIND_R2: case RGUI_SETTINGS_BIND_L3: case RGUI_SETTINGS_BIND_R3: case RGUI_SETTINGS_BIND_ANALOG_LEFT_X_PLUS: case RGUI_SETTINGS_BIND_ANALOG_LEFT_X_MINUS: case RGUI_SETTINGS_BIND_ANALOG_LEFT_Y_PLUS: case RGUI_SETTINGS_BIND_ANALOG_LEFT_Y_MINUS: case RGUI_SETTINGS_BIND_ANALOG_RIGHT_X_PLUS: case RGUI_SETTINGS_BIND_ANALOG_RIGHT_X_MINUS: case RGUI_SETTINGS_BIND_ANALOG_RIGHT_Y_PLUS: case RGUI_SETTINGS_BIND_ANALOG_RIGHT_Y_MINUS: case RGUI_SETTINGS_BIND_MENU_TOGGLE: if (driver.input->set_keybinds) { unsigned keybind_action = KEYBINDS_ACTION_NONE; if (action == RGUI_ACTION_START) keybind_action = (1ULL << KEYBINDS_ACTION_SET_DEFAULT_BIND); // FIXME: The array indices here look totally wrong ... Fixed it so it looks kind of sane for now. if (keybind_action != KEYBINDS_ACTION_NONE) driver.input->set_keybinds(driver.input_data, g_settings.input.device[port], port, setting - RGUI_SETTINGS_BIND_BEGIN, keybind_action); } else { struct retro_keybind *bind = &g_settings.input.binds[port][setting - RGUI_SETTINGS_BIND_BEGIN]; if (action == RGUI_ACTION_OK) { rgui->binds.begin = setting; rgui->binds.last = setting; rgui->binds.target = bind; rgui->binds.player = port; rgui_list_push(rgui->menu_stack, "", RGUI_SETTINGS_CUSTOM_BIND, rgui->selection_ptr); menu_poll_bind_get_rested_axes(&rgui->binds); menu_poll_bind_state(&rgui->binds); } else if (action == RGUI_ACTION_START) { bind->joykey = NO_BTN; bind->joyaxis = AXIS_NONE; } } break; case RGUI_BROWSER_DIR_PATH: if (action == RGUI_ACTION_START) { *g_settings.rgui_browser_directory = '\0'; *rgui->base_path = '\0'; } break; #ifdef HAVE_SCREENSHOTS case RGUI_SCREENSHOT_DIR_PATH: if (action == RGUI_ACTION_START) *g_settings.screenshot_directory = '\0'; break; #endif case RGUI_SAVEFILE_DIR_PATH: if (action == RGUI_ACTION_START) *g_extern.savefile_dir = '\0'; break; #ifdef HAVE_OVERLAY case RGUI_OVERLAY_DIR_PATH: if (action == RGUI_ACTION_START) *g_extern.overlay_dir = '\0'; break; #endif case RGUI_SAVESTATE_DIR_PATH: if (action == RGUI_ACTION_START) *g_extern.savestate_dir = '\0'; break; #ifdef HAVE_DYNAMIC case RGUI_LIBRETRO_DIR_PATH: if (action == RGUI_ACTION_START) { *rgui->libretro_dir = '\0'; menu_init_core_info(rgui); } break; #endif case RGUI_LIBRETRO_INFO_DIR_PATH: if (action == RGUI_ACTION_START) { *g_settings.libretro_info_path = '\0'; menu_init_core_info(rgui); } break; case RGUI_CONFIG_DIR_PATH: if (action == RGUI_ACTION_START) *g_settings.rgui_config_directory = '\0'; break; case RGUI_SHADER_DIR_PATH: if (action == RGUI_ACTION_START) *g_settings.video.shader_dir = '\0'; break; case RGUI_SYSTEM_DIR_PATH: if (action == RGUI_ACTION_START) *g_settings.system_directory = '\0'; break; case RGUI_SETTINGS_VIDEO_ROTATION: if (action == RGUI_ACTION_START) { settings_set(1ULL << S_DEF_ROTATION); video_set_rotation_func((g_settings.video.rotation + g_extern.system.rotation) % 4); } else if (action == RGUI_ACTION_LEFT) { settings_set(1ULL << S_ROTATION_DECREMENT); video_set_rotation_func((g_settings.video.rotation + g_extern.system.rotation) % 4); } else if (action == RGUI_ACTION_RIGHT) { settings_set(1ULL << S_ROTATION_INCREMENT); video_set_rotation_func((g_settings.video.rotation + g_extern.system.rotation) % 4); } break; case RGUI_SETTINGS_VIDEO_FILTER: if (action == RGUI_ACTION_START) settings_set(1ULL << S_DEF_HW_TEXTURE_FILTER); else settings_set(1ULL << S_HW_TEXTURE_FILTER); if (driver.video_poke->set_filtering) driver.video_poke->set_filtering(driver.video_data, 1, g_settings.video.smooth); break; case RGUI_SETTINGS_VIDEO_GAMMA: if (action == RGUI_ACTION_START) { g_extern.console.screen.gamma_correction = 0; if (driver.video_poke->apply_state_changes) driver.video_poke->apply_state_changes(driver.video_data); } else if (action == RGUI_ACTION_LEFT) { if(g_extern.console.screen.gamma_correction > 0) { g_extern.console.screen.gamma_correction--; if (driver.video_poke->apply_state_changes) driver.video_poke->apply_state_changes(driver.video_data); } } else if (action == RGUI_ACTION_RIGHT) { if(g_extern.console.screen.gamma_correction < MAX_GAMMA_SETTING) { g_extern.console.screen.gamma_correction++; if (driver.video_poke->apply_state_changes) driver.video_poke->apply_state_changes(driver.video_data); } } break; case RGUI_SETTINGS_VIDEO_INTEGER_SCALE: if (action == RGUI_ACTION_START) settings_set(1ULL << S_DEF_SCALE_INTEGER); else if (action == RGUI_ACTION_LEFT || action == RGUI_ACTION_RIGHT || action == RGUI_ACTION_OK) settings_set(1ULL << S_SCALE_INTEGER_TOGGLE); if (driver.video_poke->apply_state_changes) driver.video_poke->apply_state_changes(driver.video_data); break; case RGUI_SETTINGS_VIDEO_ASPECT_RATIO: if (action == RGUI_ACTION_START) settings_set(1ULL << S_DEF_ASPECT_RATIO); else if (action == RGUI_ACTION_LEFT) settings_set(1ULL << S_ASPECT_RATIO_DECREMENT); else if (action == RGUI_ACTION_RIGHT) settings_set(1ULL << S_ASPECT_RATIO_INCREMENT); if (driver.video_poke->set_aspect_ratio) driver.video_poke->set_aspect_ratio(driver.video_data, g_settings.video.aspect_ratio_idx); break; case RGUI_SETTINGS_TOGGLE_FULLSCREEN: if (action == RGUI_ACTION_OK) rarch_set_fullscreen(!g_settings.video.fullscreen); break; #if defined(GEKKO) case RGUI_SETTINGS_VIDEO_RESOLUTION: if (action == RGUI_ACTION_LEFT) { if(rgui_current_gx_resolution > 0) { rgui_current_gx_resolution--; gx_set_video_mode(rgui_gx_resolutions[rgui_current_gx_resolution][0], rgui_gx_resolutions[rgui_current_gx_resolution][1]); } } else if (action == RGUI_ACTION_RIGHT) { if (rgui_current_gx_resolution < GX_RESOLUTIONS_LAST - 1) { #ifdef HW_RVL if ((rgui_current_gx_resolution + 1) > GX_RESOLUTIONS_640_480) if (CONF_GetVideo() != CONF_VIDEO_PAL) return 0; #endif rgui_current_gx_resolution++; gx_set_video_mode(rgui_gx_resolutions[rgui_current_gx_resolution][0], rgui_gx_resolutions[rgui_current_gx_resolution][1]); } } break; #elif defined(__CELLOS_LV2__) case RGUI_SETTINGS_VIDEO_RESOLUTION: if (action == RGUI_ACTION_LEFT) settings_set(1ULL << S_RESOLUTION_PREVIOUS); else if (action == RGUI_ACTION_RIGHT) settings_set(1ULL << S_RESOLUTION_NEXT); else if (action == RGUI_ACTION_OK) { if (g_extern.console.screen.resolutions.list[g_extern.console.screen.resolutions.current.idx] == CELL_VIDEO_OUT_RESOLUTION_576) { if (g_extern.console.screen.pal_enable) g_extern.lifecycle_mode_state |= (1ULL<< MODE_VIDEO_PAL_ENABLE); } else { g_extern.lifecycle_mode_state &= ~(1ULL << MODE_VIDEO_PAL_ENABLE); g_extern.lifecycle_mode_state &= ~(1ULL << MODE_VIDEO_PAL_TEMPORAL_ENABLE); } driver.video->restart(); rgui_init_textures(); } break; #endif #ifdef HW_RVL case RGUI_SETTINGS_VIDEO_SOFT_FILTER: if (g_extern.lifecycle_mode_state & (1ULL << MODE_VIDEO_SOFT_FILTER_ENABLE)) g_extern.lifecycle_mode_state &= ~(1ULL << MODE_VIDEO_SOFT_FILTER_ENABLE); else g_extern.lifecycle_mode_state |= (1ULL << MODE_VIDEO_SOFT_FILTER_ENABLE); if (driver.video_poke->apply_state_changes) driver.video_poke->apply_state_changes(driver.video_data); break; #endif case RGUI_SETTINGS_VIDEO_VSYNC: switch (action) { case RGUI_ACTION_START: settings_set(1ULL << S_DEF_VIDEO_VSYNC); break; case RGUI_ACTION_LEFT: case RGUI_ACTION_RIGHT: case RGUI_ACTION_OK: settings_set(1ULL << S_VIDEO_VSYNC_TOGGLE); break; default: break; } break; case RGUI_SETTINGS_VIDEO_HARD_SYNC: switch (action) { case RGUI_ACTION_START: g_settings.video.hard_sync = false; break; case RGUI_ACTION_LEFT: case RGUI_ACTION_RIGHT: case RGUI_ACTION_OK: g_settings.video.hard_sync = !g_settings.video.hard_sync; break; default: break; } break; case RGUI_SETTINGS_VIDEO_BLACK_FRAME_INSERTION: switch (action) { case RGUI_ACTION_START: g_settings.video.black_frame_insertion = false; break; case RGUI_ACTION_LEFT: case RGUI_ACTION_RIGHT: case RGUI_ACTION_OK: g_settings.video.black_frame_insertion = !g_settings.video.black_frame_insertion; break; default: break; } break; case RGUI_SETTINGS_VIDEO_CROP_OVERSCAN: switch (action) { case RGUI_ACTION_START: g_settings.video.crop_overscan = true; break; case RGUI_ACTION_LEFT: case RGUI_ACTION_RIGHT: case RGUI_ACTION_OK: g_settings.video.crop_overscan = !g_settings.video.crop_overscan; break; default: break; } break; case RGUI_SETTINGS_VIDEO_WINDOW_SCALE_X: case RGUI_SETTINGS_VIDEO_WINDOW_SCALE_Y: { float *scale = setting == RGUI_SETTINGS_VIDEO_WINDOW_SCALE_X ? &g_settings.video.xscale : &g_settings.video.yscale; float old_scale = *scale; switch (action) { case RGUI_ACTION_START: *scale = 3.0f; break; case RGUI_ACTION_LEFT: *scale -= 1.0f; break; case RGUI_ACTION_RIGHT: *scale += 1.0f; break; default: break; } *scale = roundf(*scale); *scale = max(*scale, 1.0f); if (old_scale != *scale && !g_settings.video.fullscreen) rarch_set_fullscreen(g_settings.video.fullscreen); // Reinit video driver. break; } #ifdef HAVE_THREADS case RGUI_SETTINGS_VIDEO_THREADED: { bool old = g_settings.video.threaded; if (action == RGUI_ACTION_OK || action == RGUI_ACTION_LEFT || action == RGUI_ACTION_RIGHT) g_settings.video.threaded = !g_settings.video.threaded; else if (action == RGUI_ACTION_START) g_settings.video.threaded = false; if (g_settings.video.threaded != old) rarch_set_fullscreen(g_settings.video.fullscreen); // Reinit video driver. break; } #endif case RGUI_SETTINGS_VIDEO_SWAP_INTERVAL: { unsigned old = g_settings.video.swap_interval; switch (action) { case RGUI_ACTION_START: g_settings.video.swap_interval = 1; break; case RGUI_ACTION_LEFT: g_settings.video.swap_interval--; break; case RGUI_ACTION_RIGHT: case RGUI_ACTION_OK: g_settings.video.swap_interval++; break; default: break; } g_settings.video.swap_interval = min(g_settings.video.swap_interval, 4); g_settings.video.swap_interval = max(g_settings.video.swap_interval, 1); if (old != g_settings.video.swap_interval && driver.video && driver.video_data) video_set_nonblock_state_func(false); // This will update the current swap interval. Since we're in RGUI now, always apply VSync. break; } case RGUI_SETTINGS_VIDEO_HARD_SYNC_FRAMES: switch (action) { case RGUI_ACTION_START: g_settings.video.hard_sync_frames = 0; break; case RGUI_ACTION_LEFT: if (g_settings.video.hard_sync_frames > 0) g_settings.video.hard_sync_frames--; break; case RGUI_ACTION_RIGHT: case RGUI_ACTION_OK: if (g_settings.video.hard_sync_frames < 3) g_settings.video.hard_sync_frames++; break; default: break; } break; case RGUI_SETTINGS_VIDEO_REFRESH_RATE_AUTO: switch (action) { case RGUI_ACTION_START: g_extern.measure_data.frame_time_samples_count = 0; break; case RGUI_ACTION_OK: { double refresh_rate = 0.0; double deviation = 0.0; unsigned sample_points = 0; if (driver_monitor_fps_statistics(&refresh_rate, &deviation, &sample_points)) { driver_set_monitor_refresh_rate(refresh_rate); // Incase refresh rate update forced non-block video. video_set_nonblock_state_func(false); } break; } default: break; } break; #ifdef HAVE_SHADER_MANAGER case RGUI_SETTINGS_SHADER_PASSES: switch (action) { case RGUI_ACTION_START: rgui->shader.passes = 0; break; case RGUI_ACTION_LEFT: if (rgui->shader.passes) rgui->shader.passes--; break; case RGUI_ACTION_RIGHT: case RGUI_ACTION_OK: if (rgui->shader.passes < RGUI_MAX_SHADERS) rgui->shader.passes++; break; default: break; } #ifndef HAVE_RMENU rgui->need_refresh = true; #endif break; case RGUI_SETTINGS_SHADER_APPLY: { if (!driver.video->set_shader || action != RGUI_ACTION_OK) return 0; RARCH_LOG("Applying shader ...\n"); enum rarch_shader_type type = shader_manager_get_type(&rgui->shader); if (rgui->shader.passes && type != RARCH_SHADER_NONE) { const char *conf_path = type == RARCH_SHADER_GLSL ? rgui->default_glslp : rgui->default_cgp; char config_directory[PATH_MAX]; if (*g_extern.config_path) fill_pathname_basedir(config_directory, g_extern.config_path, sizeof(config_directory)); else *config_directory = '\0'; char cgp_path[PATH_MAX]; const char *dirs[] = { g_settings.video.shader_dir, g_settings.rgui_config_directory, config_directory, }; config_file_t *conf = config_file_new(NULL); if (!conf) return 0; gfx_shader_write_conf_cgp(conf, &rgui->shader); bool ret = false; unsigned d; for (d = 0; d < ARRAY_SIZE(dirs); d++) { if (!*dirs[d]) continue; fill_pathname_join(cgp_path, dirs[d], conf_path, sizeof(cgp_path)); if (config_file_write(conf, cgp_path)) { RARCH_LOG("Saved shader preset to %s.\n", cgp_path); shader_manager_set_preset(NULL, type, cgp_path); ret = true; break; } else RARCH_LOG("Failed writing shader preset to %s.\n", cgp_path); } config_file_free(conf); if (!ret) RARCH_ERR("Failed to save shader preset. Make sure config directory and/or shader dir are writable.\n"); } else { type = gfx_shader_parse_type("", DEFAULT_SHADER_TYPE); if (type == RARCH_SHADER_NONE) { #if defined(HAVE_GLSL) type = RARCH_SHADER_GLSL; #elif defined(HAVE_CG) || defined(HAVE_HLSL) type = RARCH_SHADER_CG; #endif } shader_manager_set_preset(NULL, type, NULL); } } break; #endif default: break; } return 0; }
static bool input_overlay_load_desc(input_overlay_t *ol, struct overlay_desc *desc, unsigned ol_idx, unsigned desc_idx, unsigned width, unsigned height, bool normalized, float alpha_mod, float range_mod) { bool ret = true, by_pixel; char overlay_desc_key[64], overlay_desc_image_key[64], conf_key[64], overlay_desc_normalized_key[64], image_path[PATH_MAX_LENGTH]; char overlay[256], *save, *key; float width_mod, height_mod; struct string_list *list = NULL; const char *x = NULL; const char *y = NULL; const char *box = NULL; config_file_t *conf = config_file_new(ol->overlay_path); if (!conf) { ret = false; goto end; } snprintf(overlay_desc_key, sizeof(overlay_desc_key), "overlay%u_desc%u", ol_idx, desc_idx); snprintf(overlay_desc_image_key, sizeof(overlay_desc_image_key), "overlay%u_desc%u_overlay", ol_idx, desc_idx); if (config_get_path(conf, overlay_desc_image_key, image_path, sizeof(image_path))) { char path[PATH_MAX_LENGTH]; struct texture_image img = {0}; fill_pathname_resolve_relative(path, ol->overlay_path, image_path, sizeof(path)); if (texture_image_load(&img, path)) desc->image = img; } snprintf(overlay_desc_normalized_key, sizeof(overlay_desc_normalized_key), "overlay%u_desc%u_normalized", ol_idx, desc_idx); config_get_bool(conf, overlay_desc_normalized_key, &normalized); by_pixel = !normalized; if (by_pixel && (width == 0 || height == 0)) { RARCH_ERR("[Overlay]: Base overlay is not set and not using normalized coordinates.\n"); return false; } if (!config_get_array(conf, overlay_desc_key, overlay, sizeof(overlay))) { RARCH_ERR("[Overlay]: Didn't find key: %s.\n", overlay_desc_key); return false; } list = string_split(overlay, ", "); if (!list) { RARCH_ERR("[Overlay]: Failed to split overlay desc.\n"); return false; } if (list->size < 6) { string_list_free(list); RARCH_ERR("[Overlay]: Overlay desc is invalid. Requires at least 6 tokens.\n"); return false; } x = list->elems[1].data; y = list->elems[2].data; box = list->elems[3].data; key = list->elems[0].data; desc->key_mask = 0; if (!strcmp(key, "analog_left")) desc->type = OVERLAY_TYPE_ANALOG_LEFT; else if (!strcmp(key, "analog_right")) desc->type = OVERLAY_TYPE_ANALOG_RIGHT; else if (strstr(key, "retrok_") == key) { desc->type = OVERLAY_TYPE_KEYBOARD; desc->key_mask = input_translate_str_to_rk(key + 7); } else { const char *tmp; desc->type = OVERLAY_TYPE_BUTTONS; for (tmp = strtok_r(key, "|", &save); tmp; tmp = strtok_r(NULL, "|", &save)) { if (strcmp(tmp, "nul") != 0) desc->key_mask |= UINT64_C(1) << input_translate_str_to_bind_id(tmp); } if (desc->key_mask & (UINT64_C(1) << RARCH_OVERLAY_NEXT)) { char overlay_target_key[64]; snprintf(overlay_target_key, sizeof(overlay_target_key), "overlay%u_desc%u_next_target", ol_idx, desc_idx); config_get_array(conf, overlay_target_key, desc->next_index_name, sizeof(desc->next_index_name)); } } width_mod = by_pixel ? (1.0f / width) : 1.0f; height_mod = by_pixel ? (1.0f / height) : 1.0f; desc->x = (float)strtod(x, NULL) * width_mod; desc->y = (float)strtod(y, NULL) * height_mod; if (!strcmp(box, "radial")) desc->hitbox = OVERLAY_HITBOX_RADIAL; else if (!strcmp(box, "rect")) desc->hitbox = OVERLAY_HITBOX_RECT; else { RARCH_ERR("[Overlay]: Hitbox type (%s) is invalid. Use \"radial\" or \"rect\".\n", box); ret = false; goto end; } if ( desc->type == OVERLAY_TYPE_ANALOG_LEFT || desc->type == OVERLAY_TYPE_ANALOG_RIGHT) { if (desc->hitbox != OVERLAY_HITBOX_RADIAL) { RARCH_ERR("[Overlay]: Analog hitbox type must be \"radial\".\n"); ret = false; goto end; } char overlay_analog_saturate_key[64]; snprintf(overlay_analog_saturate_key, sizeof(overlay_analog_saturate_key), "overlay%u_desc%u_saturate_pct", ol_idx, desc_idx); if (!config_get_float(conf, overlay_analog_saturate_key, &desc->analog_saturate_pct)) desc->analog_saturate_pct = 1.0f; } desc->range_x = (float)strtod(list->elems[4].data, NULL) * width_mod; desc->range_y = (float)strtod(list->elems[5].data, NULL) * height_mod; desc->mod_x = desc->x - desc->range_x; desc->mod_w = 2.0f * desc->range_x; desc->mod_y = desc->y - desc->range_y; desc->mod_h = 2.0f * desc->range_y; snprintf(conf_key, sizeof(conf_key), "overlay%u_desc%u_alpha_mod", ol_idx, desc_idx); desc->alpha_mod = alpha_mod; config_get_float(conf, conf_key, &desc->alpha_mod); snprintf(conf_key, sizeof(conf_key), "overlay%u_desc%u_range_mod", ol_idx, desc_idx); desc->range_mod = range_mod; config_get_float(conf, conf_key, &desc->range_mod); snprintf(conf_key, sizeof(conf_key), "overlay%u_desc%u_movable", ol_idx, desc_idx); desc->movable = false; desc->delta_x = 0.0f; desc->delta_y = 0.0f; config_get_bool(conf, conf_key, &desc->movable); desc->range_x_mod = desc->range_x; desc->range_y_mod = desc->range_y; end: if (conf) config_file_free(conf); if (list) string_list_free(list); return ret; }
/** * menu_shader_manager_init: * * Initializes shader manager. **/ void menu_shader_manager_init(menu_handle_t *menu) { #ifdef HAVE_SHADER_MANAGER uint32_t ext_hash; char preset_path[PATH_MAX_LENGTH]; const char *ext = NULL; struct video_shader *shader = NULL; config_file_t *conf = NULL; const char *config_path = NULL; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); if (!menu) return; shader = (struct video_shader*)menu->shader; if (*global->core_specific_config_path && settings->core_specific_config) config_path = global->core_specific_config_path; else if (*global->config_path) config_path = global->config_path; /* In a multi-config setting, we can't have * conflicts on menu.cgp/menu.glslp. */ if (config_path) { fill_pathname_base(menu->default_glslp, config_path, sizeof(menu->default_glslp)); path_remove_extension(menu->default_glslp); strlcat(menu->default_glslp, ".glslp", sizeof(menu->default_glslp)); fill_pathname_base(menu->default_cgp, config_path, sizeof(menu->default_cgp)); path_remove_extension(menu->default_cgp); strlcat(menu->default_cgp, ".cgp", sizeof(menu->default_cgp)); } else { strlcpy(menu->default_glslp, "menu.glslp", sizeof(menu->default_glslp)); strlcpy(menu->default_cgp, "menu.cgp", sizeof(menu->default_cgp)); } ext = path_get_extension(settings->video.shader_path); ext_hash = menu_hash_calculate(ext); switch (ext_hash) { case MENU_VALUE_GLSLP: case MENU_VALUE_CGP: conf = config_file_new(settings->video.shader_path); if (conf) { if (video_shader_read_conf_cgp(conf, shader)) { video_shader_resolve_relative(shader, settings->video.shader_path); video_shader_resolve_parameters(conf, shader); } config_file_free(conf); } break; case MENU_VALUE_GLSL: case MENU_VALUE_CG: strlcpy(shader->pass[0].source.path, settings->video.shader_path, sizeof(shader->pass[0].source.path)); shader->passes = 1; break; default: { const char *shader_dir = *settings->video.shader_dir ? settings->video.shader_dir : settings->system_directory; fill_pathname_join(preset_path, shader_dir, "menu.glslp", sizeof(preset_path)); conf = config_file_new(preset_path); if (!conf) { fill_pathname_join(preset_path, shader_dir, "menu.cgp", sizeof(preset_path)); conf = config_file_new(preset_path); } if (conf) { if (video_shader_read_conf_cgp(conf, shader)) { video_shader_resolve_relative(shader, preset_path); video_shader_resolve_parameters(conf, shader); } config_file_free(conf); } } break; } #endif }
/** * menu_shader_manager_save_preset: * @basename : basename of preset * @apply : immediately set preset after saving * * Save a shader preset to disk. **/ void menu_shader_manager_save_preset( const char *basename, bool apply) { #ifdef HAVE_SHADER_MANAGER char buffer[PATH_MAX_LENGTH], config_directory[PATH_MAX_LENGTH], preset_path[PATH_MAX_LENGTH]; unsigned d, type = RARCH_SHADER_NONE; const char *dirs[3] = {0}; config_file_t *conf = NULL; bool ret = false; global_t *global = global_get_ptr(); settings_t *settings = config_get_ptr(); menu_handle_t *menu = menu_driver_get_ptr(); if (!menu) { RARCH_ERR("Cannot save shader preset, menu handle is not initialized.\n"); return; } type = menu_shader_manager_get_type(menu->shader); if (type == RARCH_SHADER_NONE) return; *config_directory = '\0'; if (basename) { strlcpy(buffer, basename, sizeof(buffer)); /* Append extension automatically as appropriate. */ if (!strstr(basename, ".cgp") && !strstr(basename, ".glslp")) { switch (type) { case RARCH_SHADER_GLSL: strlcat(buffer, ".glslp", sizeof(buffer)); break; case RARCH_SHADER_CG: strlcat(buffer, ".cgp", sizeof(buffer)); break; } } } else { const char *conf_path = (type == RARCH_SHADER_GLSL) ? menu->default_glslp : menu->default_cgp; strlcpy(buffer, conf_path, sizeof(buffer)); } if (*global->config_path) fill_pathname_basedir(config_directory, global->config_path, sizeof(config_directory)); dirs[0] = settings->video.shader_dir; dirs[1] = settings->menu_config_directory; dirs[2] = config_directory; if (!(conf = (config_file_t*)config_file_new(NULL))) return; video_shader_write_conf_cgp(conf, menu->shader); for (d = 0; d < ARRAY_SIZE(dirs); d++) { if (!*dirs[d]) continue; fill_pathname_join(preset_path, dirs[d], buffer, sizeof(preset_path)); if (config_file_write(conf, preset_path)) { RARCH_LOG("Saved shader preset to %s.\n", preset_path); if (apply) menu_shader_manager_set_preset(NULL, type, preset_path); ret = true; break; } else RARCH_LOG("Failed writing shader preset to %s.\n", preset_path); } config_file_free(conf); if (!ret) RARCH_ERR("Failed to save shader preset. Make sure config directory and/or shader dir are writable.\n"); #endif }
static void *gl_glsl_init(void *data, const char *path) { unsigned i; struct shader_program_info shader_prog_info; config_file_t *conf = NULL; const char *stock_vertex = NULL; const char *stock_fragment = NULL; glsl_shader_data_t *glsl = (glsl_shader_data_t*) calloc(1, sizeof(glsl_shader_data_t)); if (!glsl) return NULL; #ifndef HAVE_OPENGLES2 RARCH_LOG("Checking GLSL shader support ...\n"); bool shader_support = glCreateProgram && glUseProgram && glCreateShader && glDeleteShader && glShaderSource && glCompileShader && glAttachShader && glDetachShader && glLinkProgram && glGetUniformLocation && glUniform1i && glUniform1f && glUniform2fv && glUniform4fv && glUniformMatrix4fv && glGetShaderiv && glGetShaderInfoLog && glGetProgramiv && glGetProgramInfoLog && glDeleteProgram && glGetAttachedShaders && glGetAttribLocation && glEnableVertexAttribArray && glDisableVertexAttribArray && glVertexAttribPointer && glGenBuffers && glBufferData && glDeleteBuffers && glBindBuffer; if (!shader_support) { RARCH_ERR("GLSL shaders aren't supported by your OpenGL driver.\n"); goto error; } #endif glsl->shader = (struct video_shader*)calloc(1, sizeof(*glsl->shader)); if (!glsl->shader) goto error; if (!string_is_empty(path)) { bool ret = false; const char *path_ext = path_get_extension(path); if (string_is_equal(path_ext, "glsl")) { strlcpy(glsl->shader->pass[0].source.path, path, sizeof(glsl->shader->pass[0].source.path)); glsl->shader->passes = 1; glsl->shader->modern = true; ret = true; } else if (string_is_equal(path_ext, "glslp")) { conf = config_file_new(path); if (conf) { ret = video_shader_read_conf_cgp(conf, glsl->shader); glsl->shader->modern = true; } } if (!ret) { RARCH_ERR("[GL]: Failed to parse GLSL shader.\n"); goto error; } } else { RARCH_WARN("[GL]: Stock GLSL shaders will be used.\n"); glsl->shader->passes = 1; glsl->shader->pass[0].source.string.vertex = strdup(glsl_core ? stock_vertex_core : stock_vertex_modern); glsl->shader->pass[0].source.string.fragment = strdup(glsl_core ? stock_fragment_core : stock_fragment_modern); glsl->shader->modern = true; } if (!string_is_empty(path)) video_shader_resolve_relative(glsl->shader, path); video_shader_resolve_parameters(conf, glsl->shader); if (conf) { config_file_free(conf); conf = NULL; } stock_vertex = (glsl->shader->modern) ? stock_vertex_modern : stock_vertex_legacy; stock_fragment = (glsl->shader->modern) ? stock_fragment_modern : stock_fragment_legacy; if (glsl_core) { stock_vertex = stock_vertex_core; stock_fragment = stock_fragment_core; } #ifdef HAVE_OPENGLES2 if (!glsl->shader->modern) { RARCH_ERR("[GL]: GLES context is used, but shader is not modern. Cannot use it.\n"); goto error; } #else if (glsl_core && !glsl->shader->modern) { RARCH_ERR("[GL]: GL core context is used, but shader is not core compatible. Cannot use it.\n"); goto error; } #endif /* Find all aliases we use in our GLSLP and add #defines for them so * that a shader can choose a fallback if we are not using a preset. */ *glsl->alias_define = '\0'; for (i = 0; i < glsl->shader->passes; i++) { if (*glsl->shader->pass[i].alias) { char define[128] = {0}; snprintf(define, sizeof(define), "#define %s_ALIAS\n", glsl->shader->pass[i].alias); strlcat(glsl->alias_define, define, sizeof(glsl->alias_define)); } } shader_prog_info.vertex = stock_vertex; shader_prog_info.fragment = stock_fragment; shader_prog_info.is_file = false; if (!gl_glsl_compile_program(glsl, 0, &glsl->prg[0], &shader_prog_info)) { RARCH_ERR("GLSL stock programs failed to compile.\n"); goto error; } if (!gl_glsl_compile_programs(glsl, &glsl->prg[1])) goto error; if (!gl_load_luts(glsl->shader, glsl->lut_textures)) { RARCH_ERR("[GL]: Failed to load LUTs.\n"); goto error; } for (i = 0; i <= glsl->shader->passes; i++) gl_glsl_find_uniforms(glsl, i, glsl->prg[i].id, &glsl->uniforms[i]); #ifdef GLSL_DEBUG if (!gl_check_error()) RARCH_WARN("Detected GL error in GLSL.\n"); #endif if (glsl->shader->variables) { retro_ctx_memory_info_t mem_info; struct state_tracker_info info = {0}; mem_info.id = RETRO_MEMORY_SYSTEM_RAM; core_get_memory(&mem_info); info.wram = (uint8_t*)mem_info.data; info.info = glsl->shader->variable; info.info_elem = glsl->shader->variables; #ifdef HAVE_PYTHON info.script = glsl->shader->script; info.script_class = *glsl->shader->script_class ? glsl->shader->script_class : NULL; #endif glsl->state_tracker = state_tracker_init(&info); if (!glsl->state_tracker) RARCH_WARN("Failed to init state tracker.\n"); } glsl->prg[glsl->shader->passes + 1] = glsl->prg[0]; glsl->uniforms[glsl->shader->passes + 1] = glsl->uniforms[0]; if (glsl->shader->modern) { shader_prog_info.vertex = glsl_core ? stock_vertex_core_blend : stock_vertex_modern_blend; shader_prog_info.fragment = glsl_core ? stock_fragment_core_blend : stock_fragment_modern_blend; shader_prog_info.is_file = false; gl_glsl_compile_program( glsl, VIDEO_SHADER_STOCK_BLEND, &glsl->prg[VIDEO_SHADER_STOCK_BLEND], &shader_prog_info ); gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_STOCK_BLEND].id, &glsl->uniforms[VIDEO_SHADER_STOCK_BLEND]); } else { glsl->prg[VIDEO_SHADER_STOCK_BLEND] = glsl->prg[0]; glsl->uniforms[VIDEO_SHADER_STOCK_BLEND] = glsl->uniforms[0]; } #ifdef HAVE_SHADERPIPELINE #if defined(HAVE_OPENGLES2) shader_prog_info.vertex = stock_vertex_xmb_simple_legacy; shader_prog_info.fragment = stock_fragment_xmb_simple; #else shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_modern : stock_vertex_xmb_legacy; shader_prog_info.fragment = stock_fragment_xmb; #endif shader_prog_info.is_file = false; gl_glsl_compile_program( glsl, VIDEO_SHADER_MENU, &glsl->prg[VIDEO_SHADER_MENU], &shader_prog_info); gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU].id, &glsl->uniforms[VIDEO_SHADER_MENU]); shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_simple_modern : stock_vertex_xmb_simple_legacy; shader_prog_info.fragment = stock_fragment_xmb_simple; gl_glsl_compile_program( glsl, VIDEO_SHADER_MENU_SEC, &glsl->prg[VIDEO_SHADER_MENU_SEC], &shader_prog_info); gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_SEC].id, &glsl->uniforms[VIDEO_SHADER_MENU_SEC]); #endif gl_glsl_reset_attrib(glsl); for (i = 0; i < GFX_MAX_SHADERS; i++) { glGenBuffers(1, &glsl->vbo[i].vbo_primary); glGenBuffers(1, &glsl->vbo[i].vbo_secondary); } return glsl; error: gl_glsl_destroy_resources(glsl); if (conf) config_file_free(conf); if (glsl) free(glsl); return NULL; }
static bool d3d_init_multipass(d3d_video_t *d3d) { unsigned i; config_file_t *conf = config_file_new(d3d->cg_shader.c_str()); if (!conf) { RARCH_ERR("Failed to load preset.\n"); return false; } memset(&d3d->shader, 0, sizeof(d3d->shader)); if (!video_shader_read_conf_cgp(conf, &d3d->shader)) { config_file_free(conf); RARCH_ERR("Failed to parse CGP file.\n"); return false; } config_file_free(conf); video_shader_resolve_relative(&d3d->shader, d3d->cg_shader.c_str()); RARCH_LOG("[D3D9 Meta-Cg] Found %u shaders.\n", d3d->shader.passes); for (i = 0; i < d3d->shader.passes; i++) { if (d3d->shader.pass[i].fbo.valid) continue; d3d->shader.pass[i].fbo.scale_x = d3d->shader.pass[i].fbo.scale_y = 1.0f; d3d->shader.pass[i].fbo.type_x = d3d->shader.pass[i].fbo.type_y = RARCH_SCALE_INPUT; } bool use_extra_pass = d3d->shader.passes < GFX_MAX_SHADERS && d3d->shader.pass[d3d->shader.passes - 1].fbo.valid; if (use_extra_pass) { d3d->shader.passes++; video_shader_pass *dummy_pass = (video_shader_pass*) &d3d->shader.pass[d3d->shader.passes - 1]; dummy_pass->fbo.scale_x = dummy_pass->fbo.scale_y = 1.0f; dummy_pass->fbo.type_x = dummy_pass->fbo.type_y = RARCH_SCALE_VIEWPORT; dummy_pass->filter = RARCH_FILTER_UNSPEC; } else { video_shader_pass *pass = (video_shader_pass*) &d3d->shader.pass[d3d->shader.passes - 1]; pass->fbo.scale_x = pass->fbo.scale_y = 1.0f; pass->fbo.type_x = pass->fbo.type_y = RARCH_SCALE_VIEWPORT; } return true; }
static bool gl_glsl_init(const char *path) { #if !defined(HAVE_OPENGLES2) && !defined(HAVE_OPENGL_MODERN) && !defined(__APPLE__) // Load shader functions. LOAD_GL_SYM(CreateProgram); LOAD_GL_SYM(UseProgram); LOAD_GL_SYM(CreateShader); LOAD_GL_SYM(DeleteShader); LOAD_GL_SYM(ShaderSource); LOAD_GL_SYM(CompileShader); LOAD_GL_SYM(AttachShader); LOAD_GL_SYM(DetachShader); LOAD_GL_SYM(LinkProgram); LOAD_GL_SYM(GetUniformLocation); LOAD_GL_SYM(Uniform1i); LOAD_GL_SYM(Uniform1f); LOAD_GL_SYM(Uniform2fv); LOAD_GL_SYM(Uniform4fv); LOAD_GL_SYM(UniformMatrix4fv); LOAD_GL_SYM(GetShaderiv); LOAD_GL_SYM(GetShaderInfoLog); LOAD_GL_SYM(GetProgramiv); LOAD_GL_SYM(GetProgramInfoLog); LOAD_GL_SYM(DeleteProgram); LOAD_GL_SYM(GetAttachedShaders); LOAD_GL_SYM(GetAttribLocation); LOAD_GL_SYM(EnableVertexAttribArray); LOAD_GL_SYM(DisableVertexAttribArray); LOAD_GL_SYM(VertexAttribPointer); LOAD_GL_SYM(GenBuffers); LOAD_GL_SYM(BufferData); LOAD_GL_SYM(DeleteBuffers); LOAD_GL_SYM(BindBuffer); RARCH_LOG("Checking GLSL shader support ...\n"); bool shader_support = pglCreateProgram && pglUseProgram && pglCreateShader && pglDeleteShader && pglShaderSource && pglCompileShader && pglAttachShader && pglDetachShader && pglLinkProgram && pglGetUniformLocation && pglUniform1i && pglUniform1f && pglUniform2fv && pglUniform4fv && pglUniformMatrix4fv && pglGetShaderiv && pglGetShaderInfoLog && pglGetProgramiv && pglGetProgramInfoLog && pglDeleteProgram && pglGetAttachedShaders && pglGetAttribLocation && pglEnableVertexAttribArray && pglDisableVertexAttribArray && pglVertexAttribPointer && pglGenBuffers && pglBufferData && pglDeleteBuffers && pglBindBuffer; if (!shader_support) { RARCH_ERR("GLSL shaders aren't supported by your OpenGL driver.\n"); return false; } #endif glsl_shader = (struct gfx_shader*)calloc(1, sizeof(*glsl_shader)); if (!glsl_shader) return false; if (path) { bool ret; if (strcmp(path_get_extension(path), "glsl") == 0) { strlcpy(glsl_shader->pass[0].source.cg, path, sizeof(glsl_shader->pass[0].source.cg)); glsl_shader->passes = 1; glsl_shader->modern = true; ret = true; } else if (strcmp(path_get_extension(path), "glslp") == 0) { config_file_t *conf = config_file_new(path); if (conf) { ret = gfx_shader_read_conf_cgp(conf, glsl_shader); glsl_shader->modern = true; config_file_free(conf); } else ret = false; } else ret = gfx_shader_read_xml(path, glsl_shader); if (!ret) { RARCH_ERR("[GL]: Failed to parse GLSL shader.\n"); return false; } } else { RARCH_WARN("[GL]: Stock GLSL shaders will be used.\n"); glsl_shader->passes = 1; glsl_shader->pass[0].source.xml.vertex = strdup(stock_vertex_modern); glsl_shader->pass[0].source.xml.fragment = strdup(stock_fragment_modern); glsl_shader->modern = true; } gfx_shader_resolve_relative(glsl_shader, path); #ifdef HAVE_OPENGLES2 if (!glsl_shader->modern) { RARCH_ERR("[GL]: GLES context is used, but shader is not modern. Cannot use it.\n"); return false; } #endif const char *stock_vertex = glsl_shader->modern ? stock_vertex_modern : stock_vertex_legacy; const char *stock_fragment = glsl_shader->modern ? stock_fragment_modern : stock_fragment_legacy; if (!(gl_program[0] = compile_program(stock_vertex, stock_fragment, 0))) { RARCH_ERR("GLSL stock programs failed to compile.\n"); gl_glsl_free_shader(); return false; } if (!compile_programs(&gl_program[1])) { gl_glsl_free_shader(); return false; } if (!load_luts()) { RARCH_ERR("[GL]: Failed to load LUTs.\n"); gl_glsl_free_shader(); return false; } for (unsigned i = 0; i <= glsl_shader->passes; i++) find_uniforms(gl_program[i], &gl_uniforms[i]); #ifdef GLSL_DEBUG if (!gl_check_error()) RARCH_WARN("Detected GL error in GLSL.\n"); #endif if (glsl_shader->variables) { struct state_tracker_info info = {0}; info.wram = (uint8_t*)pretro_get_memory_data(RETRO_MEMORY_SYSTEM_RAM); info.info = glsl_shader->variable; info.info_elem = glsl_shader->variables; #ifdef HAVE_PYTHON info.script = glsl_shader->script; info.script_class = *glsl_shader->script_class ? glsl_shader->script_class : NULL; #endif gl_state_tracker = state_tracker_init(&info); if (!gl_state_tracker) RARCH_WARN("Failed to init state tracker.\n"); } glsl_enable = true; gl_program[glsl_shader->passes + 1] = gl_program[0]; gl_uniforms[glsl_shader->passes + 1] = gl_uniforms[0]; if (glsl_shader->modern) { gl_program[GL_SHADER_STOCK_BLEND] = compile_program(stock_vertex_modern_blend, stock_fragment_modern_blend, GL_SHADER_STOCK_BLEND); find_uniforms(gl_program[GL_SHADER_STOCK_BLEND], &gl_uniforms[GL_SHADER_STOCK_BLEND]); } else { gl_program[GL_SHADER_STOCK_BLEND] = gl_program[0]; gl_uniforms[GL_SHADER_STOCK_BLEND] = gl_uniforms[0]; } gl_glsl_reset_attrib(); for (unsigned i = 0; i < GFX_MAX_SHADERS; i++) { pglGenBuffers(1, &glsl_vbo[i].vbo_primary); pglGenBuffers(1, &glsl_vbo[i].vbo_secondary); } return true; }
void input_config_autoconfigure_joypad(unsigned index, const char *name, int32_t vid, int32_t pid, const char *driver) { size_t i; if (!g_settings.input.autodetect_enable) return; /* This will be the case if input driver is reinit. * No reason to spam autoconfigure messages * every time (fine in log). */ bool block_osd_spam = g_settings.input.autoconfigured[index] && name; for (i = 0; i < RARCH_BIND_LIST_END; i++) { g_settings.input.autoconf_binds[index][i].joykey = NO_BTN; g_settings.input.autoconf_binds[index][i].joyaxis = AXIS_NONE; } g_settings.input.autoconfigured[index] = false; if (!name) return; /* false = load from both cfg files and internal */ bool internal_only = !*g_settings.input.autoconfig_dir; #if defined(HAVE_BUILTIN_AUTOCONFIG) && (!defined(_WIN32) || defined(HAVE_WINXINPUT)) /* First internal */ for (i = 0; input_builtin_autoconfs[i]; i++) { config_file_t *conf = (config_file_t*) config_file_new_from_string(input_builtin_autoconfs[i]); bool success = input_try_autoconfigure_joypad_from_conf(conf, index, name, driver, vid, pid, block_osd_spam); config_file_free(conf); if (success) break; } #endif /* Now try files */ if (!internal_only) { struct string_list *list = dir_list_new( g_settings.input.autoconfig_dir, "cfg", false); if (!list) return; for (i = 0; i < list->size; i++) { config_file_t *conf = config_file_new(list->elems[i].data); if (!conf) continue; bool success = input_try_autoconfigure_joypad_from_conf(conf, index, name, driver, vid, pid, block_osd_spam); config_file_free(conf); if (success) break; } string_list_free(list); } }