static void gl_glsl_set_params(void *data, unsigned width, unsigned height, unsigned tex_width, unsigned tex_height, unsigned out_width, unsigned out_height, unsigned frame_count, const void *_info, const void *_prev_info, const void *_feedback_info, const void *_fbo_info, unsigned fbo_info_cnt) { GLfloat buffer[512]; struct glsl_attrib attribs[32]; float input_size[2], output_size[2], texture_size[2]; unsigned i, texunit = 1; const struct shader_uniforms *uni = NULL; size_t size = 0, attribs_size = 0; const struct gfx_tex_info *info = (const struct gfx_tex_info*)_info; const struct gfx_tex_info *prev_info = (const struct gfx_tex_info*)_prev_info; const struct gfx_tex_info *feedback_info = (const struct gfx_tex_info*)_feedback_info; const struct gfx_tex_info *fbo_info = (const struct gfx_tex_info*)_fbo_info; struct glsl_attrib *attr = (struct glsl_attrib*)attribs; driver_t *driver = driver_get_ptr(); global_t *global = global_get_ptr(); glsl_shader_data_t *glsl = (glsl_shader_data_t*)driver->video_shader_data; if (!glsl) return; uni = (const struct shader_uniforms*)&glsl->gl_uniforms[glsl->glsl_active_index]; (void)data; if (glsl->gl_program[glsl->glsl_active_index] == 0) return; input_size [0] = (float)width; input_size [1] = (float)height; output_size[0] = (float)out_width; output_size[1] = (float)out_height; texture_size[0] = (float)tex_width; texture_size[1] = (float)tex_height; if (uni->input_size >= 0) glUniform2fv(uni->input_size, 1, input_size); if (uni->output_size >= 0) glUniform2fv(uni->output_size, 1, output_size); if (uni->texture_size >= 0) glUniform2fv(uni->texture_size, 1, texture_size); if (uni->frame_count >= 0 && glsl->glsl_active_index) { unsigned modulo = glsl->shader->pass[glsl->glsl_active_index - 1].frame_count_mod; if (modulo) frame_count %= modulo; glUniform1i(uni->frame_count, frame_count); } if (uni->frame_direction >= 0) glUniform1i(uni->frame_direction, global->rewind.frame_is_reverse ? -1 : 1); for (i = 0; i < glsl->shader->luts; i++) { if (uni->lut_texture[i] < 0) continue; /* Have to rebind as HW render could override this. */ glActiveTexture(GL_TEXTURE0 + texunit); glBindTexture(GL_TEXTURE_2D, glsl->gl_teximage[i]); glUniform1i(uni->lut_texture[i], texunit); texunit++; } if (glsl->glsl_active_index) { /* Set original texture. */ if (uni->orig.texture >= 0) { /* Bind original texture. */ glActiveTexture(GL_TEXTURE0 + texunit); glUniform1i(uni->orig.texture, texunit); glBindTexture(GL_TEXTURE_2D, info->tex); texunit++; } if (uni->orig.texture_size >= 0) glUniform2fv(uni->orig.texture_size, 1, info->tex_size); if (uni->orig.input_size >= 0) glUniform2fv(uni->orig.input_size, 1, info->input_size); /* Pass texture coordinates. */ if (uni->orig.tex_coord >= 0) { attr->loc = uni->orig.tex_coord; attr->size = 2; attr->offset = size * sizeof(GLfloat); attribs_size++; attr++; memcpy(buffer + size, info->coord, 8 * sizeof(GLfloat)); size += 8; } /* Set feedback texture. */ if (uni->feedback.texture >= 0) { /* Bind original texture. */ glActiveTexture(GL_TEXTURE0 + texunit); glUniform1i(uni->feedback.texture, texunit); glBindTexture(GL_TEXTURE_2D, feedback_info->tex); texunit++; } if (uni->feedback.texture_size >= 0) glUniform2fv(uni->feedback.texture_size, 1, feedback_info->tex_size); if (uni->feedback.input_size >= 0) glUniform2fv(uni->feedback.input_size, 1, feedback_info->input_size); /* Pass texture coordinates. */ if (uni->feedback.tex_coord >= 0) { attr->loc = uni->feedback.tex_coord; attr->size = 2; attr->offset = size * sizeof(GLfloat); attribs_size++; attr++; memcpy(buffer + size, feedback_info->coord, 8 * sizeof(GLfloat)); size += 8; } /* Bind FBO textures. */ for (i = 0; i < fbo_info_cnt; i++) { if (uni->pass[i].texture) { glActiveTexture(GL_TEXTURE0 + texunit); glBindTexture(GL_TEXTURE_2D, fbo_info[i].tex); glUniform1i(uni->pass[i].texture, texunit); texunit++; } if (uni->pass[i].texture_size >= 0) glUniform2fv(uni->pass[i].texture_size, 1, fbo_info[i].tex_size); if (uni->pass[i].input_size >= 0) glUniform2fv(uni->pass[i].input_size, 1, fbo_info[i].input_size); if (uni->pass[i].tex_coord >= 0) { attr->loc = uni->pass[i].tex_coord; attr->size = 2; attr->offset = size * sizeof(GLfloat); attribs_size++; attr++; memcpy(buffer + size, fbo_info[i].coord, 8 * sizeof(GLfloat)); size += 8; } } } /* Set previous textures. Only bind if they're actually used. */ for (i = 0; i < PREV_TEXTURES; i++) { if (uni->prev[i].texture >= 0) { glActiveTexture(GL_TEXTURE0 + texunit); glBindTexture(GL_TEXTURE_2D, prev_info[i].tex); glUniform1i(uni->prev[i].texture, texunit); texunit++; } if (uni->prev[i].texture_size >= 0) glUniform2fv(uni->prev[i].texture_size, 1, prev_info[i].tex_size); if (uni->prev[i].input_size >= 0) glUniform2fv(uni->prev[i].input_size, 1, prev_info[i].input_size); /* Pass texture coordinates. */ if (uni->prev[i].tex_coord >= 0) { attr->loc = uni->prev[i].tex_coord; attr->size = 2; attr->offset = size * sizeof(GLfloat); attribs_size++; attr++; memcpy(buffer + size, prev_info[i].coord, 8 * sizeof(GLfloat)); size += 8; } } if (size) { gl_glsl_set_attribs(glsl, glsl->glsl_vbo[glsl->glsl_active_index].vbo_secondary, &glsl->glsl_vbo[glsl->glsl_active_index].buffer_secondary, &glsl->glsl_vbo[glsl->glsl_active_index].size_secondary, buffer, size, attribs, attribs_size); } glActiveTexture(GL_TEXTURE0); /* #pragma parameters. */ for (i = 0; i < glsl->shader->num_parameters; i++) { int location = glGetUniformLocation( glsl->gl_program[glsl->glsl_active_index], glsl->shader->parameters[i].id); glUniform1f(location, glsl->shader->parameters[i].current); } /* Set state parameters. */ if (glsl->gl_state_tracker) { static struct state_tracker_uniform state_info[GFX_MAX_VARIABLES]; static unsigned cnt = 0; if (glsl->glsl_active_index == 1) cnt = state_tracker_get_uniform(glsl->gl_state_tracker, state_info, GFX_MAX_VARIABLES, frame_count); for (i = 0; i < cnt; i++) { int location = glGetUniformLocation( glsl->gl_program[glsl->glsl_active_index], state_info[i].id); glUniform1f(location, state_info[i].value); } } }
/* WARNING: after we move any data * into EXECUTE_ADDR, we can no longer use any * heap memory and are restricted to the stack only. */ void system_exec_wii(const char *_path, bool should_load_game) { FILE *fp; size_t size, booter_size; void *dol; char path[PATH_MAX_LENGTH]; char game_path[PATH_MAX_LENGTH]; #ifndef IS_SALAMANDER global_t *global = global_get_ptr(); bool original_verbose = global->verbosity; global->verbosity = true; #endif /* copy heap info into stack so it survives * us moving the .dol into MEM2. */ strlcpy(path, _path, sizeof(path)); if (should_load_game) { #ifdef IS_SALAMANDER strlcpy(game_path, gx_rom_path, sizeof(game_path)); #else strlcpy(game_path, global->fullpath, sizeof(game_path)); #endif } RARCH_LOG("Attempt to load executable: [%s]\n", path); fp = fopen(path, "rb"); if (fp == NULL) { RARCH_ERR("Could not open DOL file %s.\n", path); goto exit; } fseek(fp, 0, SEEK_END); size = ftell(fp); fseek(fp, 0, SEEK_SET); /* try to allocate a buffer for it. if we can't, fail. */ dol = malloc(size); if (!dol) { RARCH_ERR("Could not execute DOL file %s.\n", path); fclose(fp); goto exit; } fread(dol, 1, size, fp); fclose(fp); fatUnmount("carda:"); fatUnmount("cardb:"); fatUnmount("sd:"); fatUnmount("usb:"); __io_wiisd.shutdown(); __io_usbstorage.shutdown(); /* don't use memcpy, there might be an overlap. */ memmove(EXECUTE_ADDR, dol, size); DCFlushRange(EXECUTE_ADDR, size); dol_copy_argv_path(path, should_load_game ? game_path : NULL); booter_size = booter_end - booter_start; memcpy(BOOTER_ADDR, booter_start, booter_size); DCFlushRange(BOOTER_ADDR, booter_size); RARCH_LOG("jumping to %08x\n", (unsigned) BOOTER_ADDR); SYS_ResetSystem(SYS_SHUTDOWN,0,0); __lwp_thread_stopmultitasking((void (*)(void)) BOOTER_ADDR); exit: (void)0; #ifndef IS_SALAMANDER global->verbosity = original_verbose; #endif }
static void gfx_ctx_ps3_get_available_resolutions(void) { unsigned i; uint32_t videomode[] = { CELL_VIDEO_OUT_RESOLUTION_480, CELL_VIDEO_OUT_RESOLUTION_576, CELL_VIDEO_OUT_RESOLUTION_960x1080, CELL_VIDEO_OUT_RESOLUTION_720, CELL_VIDEO_OUT_RESOLUTION_1280x1080, CELL_VIDEO_OUT_RESOLUTION_1440x1080, CELL_VIDEO_OUT_RESOLUTION_1600x1080, CELL_VIDEO_OUT_RESOLUTION_1080 }; uint32_t resolution_count = 0; bool defaultresolution = true; uint16_t num_videomodes = sizeof(videomode) / sizeof(uint32_t); global_t *global = global_get_ptr(); if (global->console.screen.resolutions.check) return; for (i = 0; i < num_videomodes; i++) { if (cellVideoOutGetResolutionAvailability( CELL_VIDEO_OUT_PRIMARY, videomode[i], CELL_VIDEO_OUT_ASPECT_AUTO, 0)) resolution_count++; } global->console.screen.resolutions.count = 0; global->console.screen.resolutions.list = malloc(resolution_count * sizeof(uint32_t)); for (i = 0; i < num_videomodes; i++) { if (cellVideoOutGetResolutionAvailability( CELL_VIDEO_OUT_PRIMARY, videomode[i], CELL_VIDEO_OUT_ASPECT_AUTO, 0)) { global->console.screen.resolutions.list[ global->console.screen.resolutions.count++] = videomode[i]; global->console.screen.resolutions.initial.id = videomode[i]; if (global->console.screen.resolutions.current.id == videomode[i]) { defaultresolution = false; global->console.screen.resolutions.current.idx = global->console.screen.resolutions.count-1; } } } /* In case we didn't specify a resolution - * make the last resolution that was added to the list (the highest resolution) the default resolution */ if (global->console.screen.resolutions.current.id > num_videomodes || defaultresolution) global->console.screen.resolutions.current.idx = global->console.screen.resolutions.count - 1; global->console.screen.resolutions.check = true; }
/** * recording_init: * * Initializes recording. * * Returns: true (1) if successful, otherwise false (0). **/ bool recording_init(void) { char recording_file[PATH_MAX_LENGTH] = {0}; struct ffemu_params params = {0}; global_t *global = global_get_ptr(); driver_t *driver = driver_get_ptr(); settings_t *settings = config_get_ptr(); struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); const struct retro_hw_render_callback *hw_render = (const struct retro_hw_render_callback*)video_driver_callback(); if (!global->record.enable) return false; if (global->inited.core.type == CORE_TYPE_DUMMY) { RARCH_WARN(msg_hash_to_str(MSG_USING_LIBRETRO_DUMMY_CORE_RECORDING_SKIPPED)); return false; } if (!settings->video.gpu_record && hw_render->context_type) { RARCH_WARN("%s.\n", msg_hash_to_str(MSG_HW_RENDERED_MUST_USE_POSTSHADED_RECORDING)); return false; } RARCH_LOG("%s: FPS: %.4f, Sample rate: %.4f\n", msg_hash_to_str(MSG_CUSTOM_TIMING_GIVEN), (float)av_info->timing.fps, (float)av_info->timing.sample_rate); strlcpy(recording_file, global->record.path, sizeof(recording_file)); if (global->record.use_output_dir) fill_pathname_join(recording_file, global->record.output_dir, global->record.path, sizeof(recording_file)); params.out_width = av_info->geometry.base_width; params.out_height = av_info->geometry.base_height; params.fb_width = av_info->geometry.max_width; params.fb_height = av_info->geometry.max_height; params.channels = 2; params.filename = recording_file; params.fps = av_info->timing.fps; params.samplerate = av_info->timing.sample_rate; params.pix_fmt = (video_driver_get_pixel_format() == RETRO_PIXEL_FORMAT_XRGB8888) ? FFEMU_PIX_ARGB8888 : FFEMU_PIX_RGB565; params.config = NULL; if (*global->record.config) params.config = global->record.config; if (settings->video.gpu_record && driver->video->read_viewport) { struct video_viewport vp = {0}; video_driver_viewport_info(&vp); if (!vp.width || !vp.height) { RARCH_ERR("Failed to get viewport information from video driver. " "Cannot start recording ...\n"); return false; } params.out_width = vp.width; params.out_height = vp.height; params.fb_width = next_pow2(vp.width); params.fb_height = next_pow2(vp.height); if (settings->video.force_aspect && (video_driver_get_aspect_ratio() > 0.0f)) params.aspect_ratio = video_driver_get_aspect_ratio(); else params.aspect_ratio = (float)vp.width / vp.height; params.pix_fmt = FFEMU_PIX_BGR24; global->record.gpu_width = vp.width; global->record.gpu_height = vp.height; RARCH_LOG("%s %u x %u\n", msg_hash_to_str(MSG_DETECTED_VIEWPORT_OF), vp.width, vp.height); global->record.gpu_buffer = (uint8_t*)malloc(vp.width * vp.height * 3); if (!global->record.gpu_buffer) return false; } else { if (global->record.width || global->record.height) { params.out_width = global->record.width; params.out_height = global->record.height; } if (settings->video.force_aspect && (video_driver_get_aspect_ratio() > 0.0f)) params.aspect_ratio = video_driver_get_aspect_ratio(); else params.aspect_ratio = (float)params.out_width / params.out_height; if (settings->video.post_filter_record && video_driver_frame_filter_alive()) { unsigned max_width = 0; unsigned max_height = 0; if (video_driver_frame_filter_is_32bit()) params.pix_fmt = FFEMU_PIX_ARGB8888; else params.pix_fmt = FFEMU_PIX_RGB565; rarch_softfilter_get_max_output_size( video_driver_frame_filter_get_ptr(), &max_width, &max_height); params.fb_width = next_pow2(max_width); params.fb_height = next_pow2(max_height); } } RARCH_LOG("%s %s @ %ux%u. (FB size: %ux%u pix_fmt: %u)\n", msg_hash_to_str(MSG_RECORDING_TO), global->record.path, params.out_width, params.out_height, params.fb_width, params.fb_height, (unsigned)params.pix_fmt); if (!record_driver_init_first(&driver->recording, &driver->recording_data, ¶ms)) { RARCH_ERR(msg_hash_to_str(MSG_FAILED_TO_START_RECORDING)); event_command(EVENT_CMD_GPU_RECORD_DEINIT); return false; } return true; }
/** * content_load_state: * @path : path that state will be loaded from. * * Load a state from disk to memory. * * Returns: true if successful, false otherwise. **/ static bool content_load_state(const char *path) { unsigned i; ssize_t size; retro_ctx_serialize_info_t serial_info; unsigned num_blocks = 0; void *buf = NULL; struct sram_block *blocks = NULL; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); bool ret = filestream_read_file(path, &buf, &size); RARCH_LOG("%s: \"%s\".\n", msg_hash_to_str(MSG_LOADING_STATE), path); if (!ret || size < 0) goto error; RARCH_LOG("%s: %u %s.\n", msg_hash_to_str(MSG_STATE_SIZE), (unsigned)size, msg_hash_to_str(MSG_BYTES)); if (settings->block_sram_overwrite && global->savefiles && global->savefiles->size) { RARCH_LOG("%s.\n", msg_hash_to_str(MSG_BLOCKING_SRAM_OVERWRITE)); blocks = (struct sram_block*) calloc(global->savefiles->size, sizeof(*blocks)); if (blocks) { num_blocks = global->savefiles->size; for (i = 0; i < num_blocks; i++) blocks[i].type = global->savefiles->elems[i].attr.i; } } for (i = 0; i < num_blocks; i++) { retro_ctx_memory_info_t mem_info; mem_info.id = blocks[i].type; core_ctl(CORE_CTL_RETRO_GET_MEMORY, &mem_info); blocks[i].size = mem_info.size; } for (i = 0; i < num_blocks; i++) if (blocks[i].size) blocks[i].data = malloc(blocks[i].size); /* Backup current SRAM which is overwritten by unserialize. */ for (i = 0; i < num_blocks; i++) { if (blocks[i].data) { retro_ctx_memory_info_t mem_info; const void *ptr = NULL; mem_info.id = blocks[i].type; core_ctl(CORE_CTL_RETRO_GET_MEMORY, &mem_info); ptr = mem_info.data; if (ptr) memcpy(blocks[i].data, ptr, blocks[i].size); } } serial_info.data_const = buf; serial_info.size = size; ret = core_ctl(CORE_CTL_RETRO_UNSERIALIZE, &serial_info); /* Flush back. */ for (i = 0; i < num_blocks; i++) { if (blocks[i].data) { retro_ctx_memory_info_t mem_info; void *ptr = NULL; mem_info.id = blocks[i].type; core_ctl(CORE_CTL_RETRO_GET_MEMORY, &mem_info); ptr = mem_info.data; if (ptr) memcpy(ptr, blocks[i].data, blocks[i].size); } } for (i = 0; i < num_blocks; i++) free(blocks[i].data); free(blocks); free(buf); if (!ret) goto error; return true; error: RARCH_ERR("%s \"%s\".\n", msg_hash_to_str(MSG_FAILED_TO_LOAD_STATE), path); return false; }
void set_paths_redirect(const char *path) { global_t *global = global_get_ptr(); settings_t *settings = config_get_ptr(); rarch_system_info_t *info = rarch_system_info_get_ptr(); uint32_t global_library_name_hash = ((global && info->info.library_name && (info->info.library_name[0] != '\0')) ? msg_hash_calculate(info->info.library_name) : 0); if(global_library_name_hash != 0 && (global_library_name_hash != MENU_VALUE_NO_CORE)) { /* per-core saves: append the library_name to the save location */ if (settings->sort_savefiles_enable && global->dir.savefile[0] != '\0') { strlcpy(orig_savefile_dir,global->dir.savefile, sizeof(orig_savefile_dir)); fill_pathname_dir( global->dir.savefile, global->dir.savefile, info->info.library_name, sizeof(global->dir.savefile)); /* If path doesn't exist, try to create it, * if everything fails revert to the original path. */ if(!path_is_directory(global->dir.savefile) && global->dir.savefile[0] != '\0') { path_mkdir(global->dir.savefile); if(!path_is_directory(global->dir.savefile)) { RARCH_LOG("Reverting savefile directory to %s\n", orig_savefile_dir); strlcpy(global->dir.savefile, orig_savefile_dir, sizeof(global->dir.savefile)); } } } /* per-core states: append the library_name to the save location */ if (settings->sort_savestates_enable && global->dir.savestate[0] != '\0') { strlcpy(orig_savestate_dir, global->dir.savestate, sizeof(orig_savestate_dir)); fill_pathname_dir(global->dir.savestate, global->dir.savestate, info->info.library_name, sizeof(global->dir.savestate)); /* If path doesn't exist, try to create it. * If everything fails, revert to the original path. */ if(!path_is_directory(global->dir.savestate) && global->dir.savestate[0] != '\0') { path_mkdir(global->dir.savestate); if(!path_is_directory(global->dir.savestate)) { RARCH_LOG("Reverting savestate directory to %s\n", orig_savestate_dir); strlcpy(global->dir.savestate, orig_savestate_dir, sizeof(global->dir.savestate)); } } } } if(path_is_directory(global->dir.savefile)) strlcpy(global->name.savefile, global->dir.savefile, sizeof(global->name.savefile)); if(path_is_directory(global->dir.savestate)) strlcpy(global->name.savestate, global->dir.savestate, sizeof(global->name.savestate)); if (path_is_directory(global->name.savefile)) { fill_pathname_dir(global->name.savefile, global->name.base, ".srm", sizeof(global->name.savefile)); RARCH_LOG("%s \"%s\".\n", msg_hash_to_str(MSG_REDIRECTING_SAVEFILE_TO), global->name.savefile); } if (path_is_directory(global->name.savestate)) { fill_pathname_dir(global->name.savestate, global->name.base, ".state", sizeof(global->name.savestate)); RARCH_LOG("%s \"%s\".\n", msg_hash_to_str(MSG_REDIRECTING_SAVESTATE_TO), global->name.savestate); } if (path_is_directory(global->name.cheatfile)) { fill_pathname_dir(global->name.cheatfile, global->name.base, ".state", sizeof(global->name.cheatfile)); RARCH_LOG("%s \"%s\".\n", msg_hash_to_str(MSG_REDIRECTING_CHEATFILE_TO), global->name.cheatfile); } }
static void rarch_init_savefile_paths(void) { global_t *global = global_get_ptr(); rarch_system_info_t *system = rarch_system_info_get_ptr(); event_command(EVENT_CMD_SAVEFILES_DEINIT); global->savefiles = string_list_new(); rarch_assert(global->savefiles); if (*global->subsystem) { /* For subsystems, we know exactly which RAM types are supported. */ unsigned i, j; const struct retro_subsystem_info *info = libretro_find_subsystem_info( system->special, system->num_special, global->subsystem); /* We'll handle this error gracefully later. */ unsigned num_content = min(info ? info->num_roms : 0, global->subsystem_fullpaths ? global->subsystem_fullpaths->size : 0); bool use_sram_dir = path_is_directory(global->dir.savefile); for (i = 0; i < num_content; i++) { for (j = 0; j < info->roms[i].num_memory; j++) { union string_list_elem_attr attr; char path[PATH_MAX_LENGTH] = {0}; char ext[32] = {0}; const struct retro_subsystem_memory_info *mem = (const struct retro_subsystem_memory_info*) &info->roms[i].memory[j]; snprintf(ext, sizeof(ext), ".%s", mem->extension); if (use_sram_dir) { /* Redirect content fullpath to save directory. */ strlcpy(path, global->dir.savefile, sizeof(path)); fill_pathname_dir(path, global->subsystem_fullpaths->elems[i].data, ext, sizeof(path)); } else { fill_pathname(path, global->subsystem_fullpaths->elems[i].data, ext, sizeof(path)); } attr.i = mem->type; string_list_append(global->savefiles, path, attr); } } /* Let other relevant paths be inferred from the main SRAM location. */ if (!global->has_set.save_path) fill_pathname_noext(global->name.savefile, global->name.base, ".srm", sizeof(global->name.savefile)); if (path_is_directory(global->name.savefile)) { fill_pathname_dir(global->name.savefile, global->name.base, ".srm", sizeof(global->name.savefile)); RARCH_LOG("%s \"%s\".\n", msg_hash_to_str(MSG_REDIRECTING_SAVEFILE_TO), global->name.savefile); } } else { union string_list_elem_attr attr; char savefile_name_rtc[PATH_MAX_LENGTH] = {0}; attr.i = RETRO_MEMORY_SAVE_RAM; string_list_append(global->savefiles, global->name.savefile, attr); /* Infer .rtc save path from save ram path. */ attr.i = RETRO_MEMORY_RTC; fill_pathname(savefile_name_rtc, global->name.savefile, ".rtc", sizeof(savefile_name_rtc)); string_list_append(global->savefiles, savefile_name_rtc, attr); } }
bool runloop_ctl(enum runloop_ctl_state state, void *data) { static rarch_dir_list_t runloop_shader_dir; static char runloop_fullpath[PATH_MAX_LENGTH]; static rarch_system_info_t runloop_system; static unsigned runloop_pending_windowed_scale; static retro_keyboard_event_t runloop_key_event = NULL; static unsigned runloop_max_frames = false; static bool runloop_frame_time_last = false; static bool runloop_set_frame_limit = false; static bool runloop_paused = false; static bool runloop_idle = false; static bool runloop_exec = false; static bool runloop_slowmotion = false; static bool runloop_shutdown_initiated = false; static bool runloop_core_shutdown_initiated = false; static bool runloop_perfcnt_enable = false; static bool runloop_overrides_active = false; static bool runloop_game_options_active = false; #ifdef HAVE_THREADS static slock_t *runloop_msg_queue_lock = NULL; #endif static core_info_t *core_info_current = NULL; static core_info_list_t *core_info_curr_list = NULL; settings_t *settings = config_get_ptr(); switch (state) { case RUNLOOP_CTL_DATA_ITERATE: rarch_task_check(); return true; case RUNLOOP_CTL_SHADER_DIR_DEINIT: shader_dir_free(&runloop_shader_dir); return true; case RUNLOOP_CTL_SHADER_DIR_INIT: return shader_dir_init(&runloop_shader_dir); case RUNLOOP_CTL_SYSTEM_INFO_INIT: core.retro_get_system_info(&runloop_system.info); if (!runloop_system.info.library_name) runloop_system.info.library_name = msg_hash_to_str(MSG_UNKNOWN); if (!runloop_system.info.library_version) runloop_system.info.library_version = "v0"; #ifndef RARCH_CONSOLE strlcpy(runloop_system.title_buf, msg_hash_to_str(MSG_PROGRAM), sizeof(runloop_system.title_buf)); strlcat(runloop_system.title_buf, " : ", sizeof(runloop_system.title_buf)); #endif strlcat(runloop_system.title_buf, runloop_system.info.library_name, sizeof(runloop_system.title_buf)); strlcat(runloop_system.title_buf, " ", sizeof(runloop_system.title_buf)); strlcat(runloop_system.title_buf, runloop_system.info.library_version, sizeof(runloop_system.title_buf)); strlcpy(runloop_system.valid_extensions, runloop_system.info.valid_extensions ? runloop_system.info.valid_extensions : DEFAULT_EXT, sizeof(runloop_system.valid_extensions)); runloop_system.block_extract = runloop_system.info.block_extract; break; case RUNLOOP_CTL_GET_CORE_OPTION_SIZE: { unsigned *idx = (unsigned*)data; if (!idx) return false; *idx = core_option_size(runloop_system.core_options); } return true; case RUNLOOP_CTL_HAS_CORE_OPTIONS: return runloop_system.core_options; case RUNLOOP_CTL_CURRENT_CORE_LIST_FREE: if (core_info_curr_list) core_info_list_free(core_info_curr_list); core_info_curr_list = NULL; return true; case RUNLOOP_CTL_CURRENT_CORE_LIST_INIT: core_info_curr_list = core_info_list_new(); return true; case RUNLOOP_CTL_CURRENT_CORE_LIST_GET: { core_info_list_t **core = (core_info_list_t**)data; if (!core) return false; *core = core_info_curr_list; } return true; case RUNLOOP_CTL_CURRENT_CORE_FREE: if (core_info_current) free(core_info_current); core_info_current = NULL; return true; case RUNLOOP_CTL_CURRENT_CORE_INIT: core_info_current = (core_info_t*)calloc(1, sizeof(core_info_t)); if (!core_info_current) return false; return true; case RUNLOOP_CTL_CURRENT_CORE_GET: { core_info_t **core = (core_info_t**)data; if (!core) return false; *core = core_info_current; } return true; case RUNLOOP_CTL_SYSTEM_INFO_GET: { rarch_system_info_t **system = (rarch_system_info_t**)data; if (!system) return false; *system = &runloop_system; } return true; case RUNLOOP_CTL_SYSTEM_INFO_FREE: if (runloop_system.core_options) { core_option_flush(runloop_system.core_options); core_option_free(runloop_system.core_options); } runloop_system.core_options = NULL; /* No longer valid. */ if (runloop_system.special) free(runloop_system.special); runloop_system.special = NULL; if (runloop_system.ports) free(runloop_system.ports); runloop_system.ports = NULL; runloop_key_event = NULL; global_get_ptr()->frontend_key_event = NULL; audio_driver_unset_callback(); memset(&runloop_system, 0, sizeof(rarch_system_info_t)); break; case RUNLOOP_CTL_IS_FRAME_COUNT_END: { uint64_t *frame_count = NULL; video_driver_ctl(RARCH_DISPLAY_CTL_GET_FRAME_COUNT, &frame_count); return runloop_max_frames && (*frame_count >= runloop_max_frames); } case RUNLOOP_CTL_SET_FRAME_TIME_LAST: runloop_frame_time_last = true; break; case RUNLOOP_CTL_UNSET_FRAME_TIME_LAST: runloop_frame_time_last = false; break; case RUNLOOP_CTL_SET_OVERRIDES_ACTIVE: runloop_overrides_active = true; break; case RUNLOOP_CTL_UNSET_OVERRIDES_ACTIVE: runloop_overrides_active = false; break; case RUNLOOP_CTL_IS_OVERRIDES_ACTIVE: return runloop_overrides_active; case RUNLOOP_CTL_SET_GAME_OPTIONS_ACTIVE: runloop_game_options_active = true; break; case RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE: runloop_game_options_active = false; break; case RUNLOOP_CTL_IS_GAME_OPTIONS_ACTIVE: return runloop_game_options_active; case RUNLOOP_CTL_IS_FRAME_TIME_LAST: return runloop_frame_time_last; case RUNLOOP_CTL_SET_FRAME_LIMIT: runloop_set_frame_limit = true; break; case RUNLOOP_CTL_UNSET_FRAME_LIMIT: runloop_set_frame_limit = false; break; case RUNLOOP_CTL_SHOULD_SET_FRAME_LIMIT: return runloop_set_frame_limit; case RUNLOOP_CTL_GET_PERFCNT: { bool **perfcnt = (bool**)data; if (!perfcnt) return false; *perfcnt = &runloop_perfcnt_enable; } return true; case RUNLOOP_CTL_SET_PERFCNT_ENABLE: runloop_perfcnt_enable = true; break; case RUNLOOP_CTL_UNSET_PERFCNT_ENABLE: runloop_perfcnt_enable = false; break; case RUNLOOP_CTL_IS_PERFCNT_ENABLE: return runloop_perfcnt_enable; case RUNLOOP_CTL_GET_WINDOWED_SCALE: { unsigned **scale = (unsigned**)data; if (!scale) return false; *scale = (unsigned*)&runloop_pending_windowed_scale; } break; case RUNLOOP_CTL_SET_WINDOWED_SCALE: { unsigned *idx = (unsigned*)data; if (!idx) return false; runloop_pending_windowed_scale = *idx; } break; case RUNLOOP_CTL_SET_LIBRETRO_PATH: { const char *fullpath = (const char*)data; if (!fullpath) return false; strlcpy(settings->libretro, fullpath, sizeof(settings->libretro)); } break; case RUNLOOP_CTL_CLEAR_CONTENT_PATH: *runloop_fullpath = '\0'; break; case RUNLOOP_CTL_GET_CONTENT_PATH: { char **fullpath = (char**)data; if (!fullpath) return false; *fullpath = (char*)runloop_fullpath; } break; case RUNLOOP_CTL_SET_CONTENT_PATH: { const char *fullpath = (const char*)data; if (!fullpath) return false; strlcpy(runloop_fullpath, fullpath, sizeof(runloop_fullpath)); } break; case RUNLOOP_CTL_CHECK_FOCUS: if (settings->pause_nonactive) return video_driver_ctl(RARCH_DISPLAY_CTL_IS_FOCUSED, NULL); return true; case RUNLOOP_CTL_CHECK_IDLE_STATE: { event_cmd_state_t *cmd = (event_cmd_state_t*)data; bool focused = runloop_ctl(RUNLOOP_CTL_CHECK_FOCUS, NULL); check_pause(settings, focused, runloop_cmd_triggered(cmd, RARCH_PAUSE_TOGGLE), runloop_cmd_triggered(cmd, RARCH_FRAMEADVANCE)); if (!runloop_ctl(RUNLOOP_CTL_CHECK_PAUSE_STATE, cmd) || !focused) return false; break; } case RUNLOOP_CTL_CHECK_STATE: { bool tmp = false; event_cmd_state_t *cmd = (event_cmd_state_t*)data; if (!cmd || runloop_idle) return false; if (runloop_cmd_triggered(cmd, RARCH_SCREENSHOT)) event_command(EVENT_CMD_TAKE_SCREENSHOT); if (runloop_cmd_triggered(cmd, RARCH_MUTE)) event_command(EVENT_CMD_AUDIO_MUTE_TOGGLE); if (runloop_cmd_triggered(cmd, RARCH_OSK)) { if (input_driver_ctl(RARCH_INPUT_CTL_IS_KEYBOARD_LINEFEED_ENABLED, NULL)) input_driver_ctl(RARCH_INPUT_CTL_UNSET_KEYBOARD_LINEFEED_ENABLED, NULL); else input_driver_ctl(RARCH_INPUT_CTL_SET_KEYBOARD_LINEFEED_ENABLED, NULL); } if (runloop_cmd_press(cmd, RARCH_VOLUME_UP)) event_command(EVENT_CMD_VOLUME_UP); else if (runloop_cmd_press(cmd, RARCH_VOLUME_DOWN)) event_command(EVENT_CMD_VOLUME_DOWN); #ifdef HAVE_NETPLAY tmp = runloop_cmd_triggered(cmd, RARCH_NETPLAY_FLIP); netplay_driver_ctl(RARCH_NETPLAY_CTL_FLIP_PLAYERS, &tmp); tmp = runloop_cmd_triggered(cmd, RARCH_FULLSCREEN_TOGGLE_KEY); netplay_driver_ctl(RARCH_NETPLAY_CTL_FULLSCREEN_TOGGLE, &tmp); #endif if (!runloop_ctl(RUNLOOP_CTL_CHECK_IDLE_STATE, data)) return false; check_fast_forward_button( runloop_cmd_triggered(cmd, RARCH_FAST_FORWARD_KEY), runloop_cmd_press (cmd, RARCH_FAST_FORWARD_HOLD_KEY), runloop_cmd_pressed (cmd, RARCH_FAST_FORWARD_HOLD_KEY)); check_stateslots(settings, runloop_cmd_triggered(cmd, RARCH_STATE_SLOT_PLUS), runloop_cmd_triggered(cmd, RARCH_STATE_SLOT_MINUS) ); if (runloop_cmd_triggered(cmd, RARCH_SAVE_STATE_KEY)) event_command(EVENT_CMD_SAVE_STATE); else if (runloop_cmd_triggered(cmd, RARCH_LOAD_STATE_KEY)) event_command(EVENT_CMD_LOAD_STATE); state_manager_check_rewind(runloop_cmd_press(cmd, RARCH_REWIND)); tmp = runloop_cmd_press(cmd, RARCH_SLOWMOTION); runloop_ctl(RUNLOOP_CTL_CHECK_SLOWMOTION, &tmp); if (runloop_cmd_triggered(cmd, RARCH_MOVIE_RECORD_TOGGLE)) runloop_ctl(RUNLOOP_CTL_CHECK_MOVIE, NULL); check_shader_dir(&runloop_shader_dir, runloop_cmd_triggered(cmd, RARCH_SHADER_NEXT), runloop_cmd_triggered(cmd, RARCH_SHADER_PREV)); if (runloop_cmd_triggered(cmd, RARCH_DISK_EJECT_TOGGLE)) event_command(EVENT_CMD_DISK_EJECT_TOGGLE); else if (runloop_cmd_triggered(cmd, RARCH_DISK_NEXT)) event_command(EVENT_CMD_DISK_NEXT); else if (runloop_cmd_triggered(cmd, RARCH_DISK_PREV)) event_command(EVENT_CMD_DISK_PREV); if (runloop_cmd_triggered(cmd, RARCH_RESET)) event_command(EVENT_CMD_RESET); cheat_manager_state_checks( runloop_cmd_triggered(cmd, RARCH_CHEAT_INDEX_PLUS), runloop_cmd_triggered(cmd, RARCH_CHEAT_INDEX_MINUS), runloop_cmd_triggered(cmd, RARCH_CHEAT_TOGGLE)); } break; case RUNLOOP_CTL_CHECK_PAUSE_STATE: { bool check_is_oneshot; event_cmd_state_t *cmd = (event_cmd_state_t*)data; if (!cmd) return false; check_is_oneshot = runloop_cmd_triggered(cmd, RARCH_FRAMEADVANCE) || runloop_cmd_press(cmd, RARCH_REWIND); if (!runloop_paused) return true; if (runloop_cmd_triggered(cmd, RARCH_FULLSCREEN_TOGGLE_KEY)) { event_command(EVENT_CMD_FULLSCREEN_TOGGLE); video_driver_ctl(RARCH_DISPLAY_CTL_CACHED_FRAME_RENDER, NULL); } if (!check_is_oneshot) return false; } break; case RUNLOOP_CTL_CHECK_SLOWMOTION: { bool *ptr = (bool*)data; if (!ptr) return false; runloop_slowmotion = *ptr; if (!runloop_slowmotion) return false; if (settings->video.black_frame_insertion) video_driver_ctl(RARCH_DISPLAY_CTL_CACHED_FRAME_RENDER, NULL); if (state_manager_frame_is_reversed()) runloop_msg_queue_push_new(MSG_SLOW_MOTION_REWIND, 0, 30, true); else runloop_msg_queue_push_new(MSG_SLOW_MOTION, 0, 30, true); } break; case RUNLOOP_CTL_CHECK_MOVIE: if (bsv_movie_ctl(BSV_MOVIE_CTL_PLAYBACK_ON, NULL)) return runloop_ctl(RUNLOOP_CTL_CHECK_MOVIE_PLAYBACK, NULL); if (!bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL)) return runloop_ctl(RUNLOOP_CTL_CHECK_MOVIE_INIT, NULL); return runloop_ctl(RUNLOOP_CTL_CHECK_MOVIE_RECORD, NULL); case RUNLOOP_CTL_CHECK_MOVIE_RECORD: if (!bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL)) return false; runloop_msg_queue_push_new( MSG_MOVIE_RECORD_STOPPED, 2, 180, true); RARCH_LOG("%s\n", msg_hash_to_str(MSG_MOVIE_RECORD_STOPPED)); event_command(EVENT_CMD_BSV_MOVIE_DEINIT); break; case RUNLOOP_CTL_CHECK_MOVIE_INIT: if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL)) return false; { char msg[128]; char path[PATH_MAX_LENGTH]; settings->rewind_granularity = 1; if (settings->state_slot > 0) snprintf(path, sizeof(path), "%s%d", bsv_movie_get_path(), settings->state_slot); else strlcpy(path, bsv_movie_get_path(), sizeof(path)); strlcat(path, ".bsv", sizeof(path)); snprintf(msg, sizeof(msg), "%s \"%s\".", msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO), path); bsv_movie_init_handle(path, RARCH_MOVIE_RECORD); if (!bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL)) return false; else if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL)) { runloop_msg_queue_push(msg, 1, 180, true); RARCH_LOG("%s \"%s\".\n", msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO), path); } else { runloop_msg_queue_push_new( MSG_FAILED_TO_START_MOVIE_RECORD, 1, 180, true); RARCH_ERR("%s\n", msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD)); } } break; case RUNLOOP_CTL_CHECK_MOVIE_PLAYBACK: if (!bsv_movie_ctl(BSV_MOVIE_CTL_END, NULL)) return false; runloop_msg_queue_push_new( MSG_MOVIE_PLAYBACK_ENDED, 1, 180, false); RARCH_LOG("%s\n", msg_hash_to_str(MSG_MOVIE_PLAYBACK_ENDED)); event_command(EVENT_CMD_BSV_MOVIE_DEINIT); bsv_movie_ctl(BSV_MOVIE_CTL_UNSET_END, NULL); bsv_movie_ctl(BSV_MOVIE_CTL_UNSET_PLAYBACK, NULL); break; case RUNLOOP_CTL_STATE_FREE: runloop_perfcnt_enable = false; runloop_idle = false; runloop_paused = false; runloop_slowmotion = false; runloop_frame_time_last = false; runloop_set_frame_limit = false; runloop_overrides_active = false; runloop_max_frames = 0; break; case RUNLOOP_CTL_GLOBAL_FREE: { global_t *global; event_command(EVENT_CMD_TEMPORARY_CONTENT_DEINIT); event_command(EVENT_CMD_SUBSYSTEM_FULLPATHS_DEINIT); event_command(EVENT_CMD_RECORD_DEINIT); event_command(EVENT_CMD_LOG_FILE_DEINIT); rarch_ctl(RARCH_CTL_UNSET_BLOCK_CONFIG_READ, NULL); runloop_ctl(RUNLOOP_CTL_CLEAR_CONTENT_PATH, NULL); runloop_overrides_active = false; global = global_get_ptr(); memset(global, 0, sizeof(struct global)); } break; case RUNLOOP_CTL_CLEAR_STATE: driver_ctl(RARCH_DRIVER_CTL_DEINIT, NULL); runloop_ctl(RUNLOOP_CTL_STATE_FREE, NULL); runloop_ctl(RUNLOOP_CTL_GLOBAL_FREE, NULL); break; case RUNLOOP_CTL_SET_MAX_FRAMES: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; runloop_max_frames = *ptr; } break; case RUNLOOP_CTL_IS_IDLE: return runloop_idle; case RUNLOOP_CTL_SET_IDLE: { bool *ptr = (bool*)data; if (!ptr) return false; runloop_idle = *ptr; } break; case RUNLOOP_CTL_IS_SLOWMOTION: { bool *ptr = (bool*)data; if (!ptr) return false; *ptr = runloop_slowmotion; } break; case RUNLOOP_CTL_SET_SLOWMOTION: { bool *ptr = (bool*)data; if (!ptr) return false; runloop_slowmotion = *ptr; } break; case RUNLOOP_CTL_SET_PAUSED: { bool *ptr = (bool*)data; if (!ptr) return false; runloop_paused = *ptr; } break; case RUNLOOP_CTL_IS_PAUSED: return runloop_paused; case RUNLOOP_CTL_MSG_QUEUE_FREE: #ifdef HAVE_THREADS slock_free(runloop_msg_queue_lock); runloop_msg_queue_lock = NULL; #endif break; case RUNLOOP_CTL_MSG_QUEUE_DEINIT: if (!g_msg_queue) return true; runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_LOCK, NULL); msg_queue_free(g_msg_queue); runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_UNLOCK, NULL); runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_FREE, NULL); g_msg_queue = NULL; break; case RUNLOOP_CTL_MSG_QUEUE_INIT: runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_DEINIT, NULL); g_msg_queue = msg_queue_new(8); retro_assert(g_msg_queue); #ifdef HAVE_THREADS runloop_msg_queue_lock = slock_new(); retro_assert(runloop_msg_queue_lock); #endif break; case RUNLOOP_CTL_MSG_QUEUE_LOCK: #ifdef HAVE_THREADS slock_lock(runloop_msg_queue_lock); #endif break; case RUNLOOP_CTL_MSG_QUEUE_UNLOCK: #ifdef HAVE_THREADS slock_unlock(runloop_msg_queue_lock); #endif break; case RUNLOOP_CTL_PREPARE_DUMMY: #ifdef HAVE_MENU menu_driver_ctl(RARCH_MENU_CTL_UNSET_LOAD_NO_CONTENT, NULL); #endif runloop_data_clear_state(); runloop_ctl(RUNLOOP_CTL_CLEAR_CONTENT_PATH, NULL); rarch_ctl(RARCH_CTL_LOAD_CONTENT, NULL); break; case RUNLOOP_CTL_SET_CORE_SHUTDOWN: runloop_core_shutdown_initiated = true; break; case RUNLOOP_CTL_UNSET_CORE_SHUTDOWN: runloop_core_shutdown_initiated = false; break; case RUNLOOP_CTL_IS_CORE_SHUTDOWN: return runloop_core_shutdown_initiated; case RUNLOOP_CTL_SET_SHUTDOWN: runloop_shutdown_initiated = true; break; case RUNLOOP_CTL_UNSET_SHUTDOWN: runloop_shutdown_initiated = false; break; case RUNLOOP_CTL_IS_SHUTDOWN: return runloop_shutdown_initiated; case RUNLOOP_CTL_SET_EXEC: runloop_exec = true; break; case RUNLOOP_CTL_UNSET_EXEC: runloop_exec = false; break; case RUNLOOP_CTL_IS_EXEC: return runloop_exec; case RUNLOOP_CTL_DATA_DEINIT: rarch_task_deinit(); break; case RUNLOOP_CTL_IS_CORE_OPTION_UPDATED: return runloop_system.core_options ? core_option_updated(runloop_system.core_options) : false; case RUNLOOP_CTL_CORE_OPTION_PREV: { unsigned *idx = (unsigned*)data; if (!idx) return false; core_option_prev(runloop_system.core_options, *idx); if (ui_companion_is_on_foreground()) ui_companion_driver_notify_refresh(); } return true; case RUNLOOP_CTL_CORE_OPTION_NEXT: { unsigned *idx = (unsigned*)data; if (!idx) return false; core_option_next(runloop_system.core_options, *idx); if (ui_companion_is_on_foreground()) ui_companion_driver_notify_refresh(); } return true; case RUNLOOP_CTL_CORE_OPTIONS_GET: { struct retro_variable *var = (struct retro_variable*)data; if (!runloop_system.core_options || !var) return false; RARCH_LOG("Environ GET_VARIABLE %s:\n", var->key); core_option_get(runloop_system.core_options, var); RARCH_LOG("\t%s\n", var->value ? var->value : "N/A"); } return true; case RUNLOOP_CTL_CORE_OPTIONS_INIT: { char *game_options_path = NULL; bool ret = false; const struct retro_variable *vars = (const struct retro_variable*)data; char buf[PATH_MAX_LENGTH] = {0}; global_t *global = global_get_ptr(); const char *options_path = settings->core_options_path; if (!*options_path && *global->path.config) { fill_pathname_resolve_relative(buf, global->path.config, "retroarch-core-options.cfg", sizeof(buf)); options_path = buf; } if (settings->game_specific_options) ret = rarch_game_specific_options(&game_options_path); if(ret) { runloop_ctl(RUNLOOP_CTL_SET_GAME_OPTIONS_ACTIVE, NULL); runloop_system.core_options = core_option_new(game_options_path, vars); free(game_options_path); } else { runloop_ctl(RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE, NULL); runloop_system.core_options = core_option_new(options_path, vars); } } break; case RUNLOOP_CTL_CORE_OPTIONS_DEINIT: if (!runloop_system.core_options) return false; core_option_flush(runloop_system.core_options); core_option_free(runloop_system.core_options); runloop_system.core_options = NULL; return true; case RUNLOOP_CTL_KEY_EVENT_GET: { retro_keyboard_event_t **key_event = (retro_keyboard_event_t**)data; if (!key_event) return false; *key_event = &runloop_key_event; } break; case RUNLOOP_CTL_NONE: default: return false; } return true; }
/** * main_entry: * * Main function of RetroArch. * * If HAVE_MAIN is not defined, will contain main loop and will not * be exited from until we exit the program. Otherwise, will * just do initialization. * * Returns: varies per platform. **/ int rarch_main(int argc, char *argv[], void *data) { void *args = (void*)data; int ret = 0; settings_t *settings = NULL; rarch_ctl(RARCH_CTL_PREINIT, NULL); frontend_driver_init_first(args); rarch_ctl(RARCH_CTL_INIT, NULL); #ifdef HAVE_THREADS async_jobs = async_job_new(); #endif if (frontend_driver_is_inited()) { if (!(ret = (main_load_content(argc, argv, args, frontend_driver_environment_get_ptr())))) return ret; } event_command(EVENT_CMD_HISTORY_INIT); settings = config_get_ptr(); if (settings->history_list_enable) { char *fullpath = NULL; global_t *global = global_get_ptr(); rarch_system_info_t *system = rarch_system_info_get_ptr(); runloop_ctl(RUNLOOP_CTL_GET_CONTENT_PATH, &fullpath); if (global->inited.content || system->no_content) history_playlist_push( g_defaults.history, fullpath, settings->libretro, system ? &system->info : NULL); } ui_companion_driver_init_first(); #ifndef HAVE_MAIN do { unsigned sleep_ms = 0; ret = runloop_iterate(&sleep_ms); if (ret == 1 && sleep_ms > 0) retro_sleep(sleep_ms); runloop_data_iterate(); }while(ret != -1); main_exit(args); #endif #ifdef HAVE_THREADS async_job_free(async_jobs); async_jobs = NULL; #endif return 0; }
/** * main_entry: * * Main function of RetroArch. * * If HAVE_MAIN is not defined, will contain main loop and will not * be exited from until we exit the program. Otherwise, will * just do initialization. * * Returns: varies per platform. **/ int rarch_main(int argc, char *argv[], void *data) { void *args = (void*)data; int ret = 0; settings_t *settings = NULL; driver_t *driver = NULL; rarch_main_alloc(); driver = driver_get_ptr(); if (driver) driver->frontend_ctx = (frontend_ctx_driver_t*)frontend_ctx_init_first(); if (!driver || !driver->frontend_ctx) RARCH_WARN("Frontend context could not be initialized.\n"); if (driver->frontend_ctx && driver->frontend_ctx->init) driver->frontend_ctx->init(args); rarch_main_new(); if (driver->frontend_ctx) { if (!(ret = (main_load_content(argc, argv, args, driver->frontend_ctx->environment_get, driver->frontend_ctx->process_args)))) return ret; } event_command(EVENT_CMD_HISTORY_INIT); settings = config_get_ptr(); if (settings->history_list_enable) { global_t *global = global_get_ptr(); rarch_system_info_t *system = rarch_system_info_get_ptr(); if (global->inited.content || system->no_content) history_playlist_push( g_defaults.history, global->path.fullpath, settings->libretro, system ? &system->info : NULL); } if (driver) driver->ui_companion = (ui_companion_driver_t*)ui_companion_init_first(); if (driver->ui_companion && driver->ui_companion->toggle) { if (settings->ui.companion_start_on_boot) driver->ui_companion->toggle(driver->ui_companion_data); } #ifndef HAVE_MAIN do{ ret = rarch_main_iterate(); if (ret == 1) rarch_sleep(10); rarch_main_data_iterate(); }while(ret != -1); main_exit(args); #endif return 0; }
/** * runloop_iterate: * * Run Libretro core in RetroArch for one frame. * * Returns: 0 on success, 1 if we have to wait until button input in order * to wake up the loop, -1 if we forcibly quit out of the RetroArch iteration loop. **/ int runloop_iterate(unsigned *sleep_ms) { unsigned i; event_cmd_state_t cmd; event_cmd_state_t *cmd_ptr = &cmd; retro_time_t current, target, to_sleep_ms; static retro_usec_t frame_time_last = 0; static retro_time_t frame_limit_minimum_time = 0.0; static retro_time_t frame_limit_last_time = 0.0; static retro_input_t last_input = 0; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); rarch_system_info_t *system = NULL; cmd.state[1] = last_input; cmd.state[0] = input_keys_pressed(); last_input = cmd.state[0]; runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system); if (runloop_ctl(RUNLOOP_CTL_IS_FRAME_TIME_LAST, NULL)) { frame_time_last = 0; runloop_ctl(RUNLOOP_CTL_UNSET_FRAME_TIME_LAST, NULL); } if (runloop_ctl(RUNLOOP_CTL_SHOULD_SET_FRAME_LIMIT, NULL)) { struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); float fastforward_ratio = (settings->fastforward_ratio == 0.0f) ? 1.0f : settings->fastforward_ratio; frame_limit_last_time = retro_get_time_usec(); frame_limit_minimum_time = (retro_time_t)roundf(1000000.0f / (av_info->timing.fps * fastforward_ratio)); runloop_ctl(RUNLOOP_CTL_UNSET_FRAME_LIMIT, NULL); } if (input_driver_ctl(RARCH_INPUT_CTL_IS_FLUSHING_INPUT, NULL)) { input_driver_ctl(RARCH_INPUT_CTL_UNSET_FLUSHING_INPUT, NULL); if (cmd.state[0]) { cmd.state[0] = 0; /* If core was paused before entering menu, evoke * pause toggle to wake it up. */ if (runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL)) BIT64_SET(cmd.state[0], RARCH_PAUSE_TOGGLE); input_driver_ctl(RARCH_INPUT_CTL_SET_FLUSHING_INPUT, NULL); } } if (system->frame_time.callback) { /* Updates frame timing if frame timing callback is in use by the core. * Limits frame time if fast forward ratio throttle is enabled. */ bool is_slowmotion; retro_time_t current = retro_get_time_usec(); retro_time_t delta = current - frame_time_last; bool is_locked_fps = (runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL) || input_driver_ctl(RARCH_INPUT_CTL_IS_NONBLOCK_STATE, NULL)) | !!recording_driver_get_data_ptr(); runloop_ctl(RUNLOOP_CTL_IS_SLOWMOTION, &is_slowmotion); if (!frame_time_last || is_locked_fps) delta = system->frame_time.reference; if (!is_locked_fps && is_slowmotion) delta /= settings->slowmotion_ratio; frame_time_last = current; if (is_locked_fps) frame_time_last = 0; system->frame_time.callback(delta); } cmd.state[2] = cmd.state[0] & ~cmd.state[1]; /* trigger */ if (runloop_cmd_triggered(cmd_ptr, RARCH_OVERLAY_NEXT)) event_command(EVENT_CMD_OVERLAY_NEXT); if (runloop_cmd_triggered(cmd_ptr, RARCH_FULLSCREEN_TOGGLE_KEY)) { bool fullscreen_toggled = !runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL); #ifdef HAVE_MENU fullscreen_toggled = fullscreen_toggled || menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL); #endif if (fullscreen_toggled) event_command(EVENT_CMD_FULLSCREEN_TOGGLE); } if (runloop_cmd_triggered(cmd_ptr, RARCH_GRAB_MOUSE_TOGGLE)) event_command(EVENT_CMD_GRAB_MOUSE_TOGGLE); #ifdef HAVE_MENU if (runloop_cmd_menu_press(cmd_ptr) || (global->inited.core.type == CORE_TYPE_DUMMY)) { if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) { if (global->inited.main && (global->inited.core.type != CORE_TYPE_DUMMY)) rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); } else rarch_ctl(RARCH_CTL_MENU_RUNNING, NULL); } #endif #ifdef HAVE_OVERLAY runloop_iterate_linefeed_overlay(settings); #endif if (runloop_iterate_time_to_exit(runloop_cmd_press(cmd_ptr, RARCH_QUIT_KEY)) != 1) { frame_limit_last_time = 0.0; return -1; } #ifdef HAVE_MENU if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) { bool focused = runloop_ctl(RUNLOOP_CTL_CHECK_FOCUS, NULL) && !ui_companion_is_on_foreground(); bool is_idle = runloop_ctl(RUNLOOP_CTL_IS_IDLE, NULL); if (menu_driver_iterate((enum menu_action)menu_input_frame_retropad(cmd.state[0], cmd.state[2])) == -1) rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); if (focused || !is_idle) menu_driver_ctl(RARCH_MENU_CTL_RENDER, NULL); if (!focused || is_idle) { *sleep_ms = 10; return 1; } goto end; } #endif if (!runloop_ctl(RUNLOOP_CTL_CHECK_STATE, &cmd)) { /* RetroArch has been paused. */ retro_ctx.poll_cb(); *sleep_ms = 10; return 1; } #if defined(HAVE_THREADS) lock_autosave(); #endif #ifdef HAVE_NETPLAY netplay_driver_ctl(RARCH_NETPLAY_CTL_PRE_FRAME, NULL); #endif if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL)) bsv_movie_ctl(BSV_MOVIE_CTL_SET_FRAME_START, NULL); if (system->camera_callback.caps) driver_camera_poll(); /* Update binds for analog dpad modes. */ for (i = 0; i < settings->input.max_users; i++) { if (!settings->input.analog_dpad_mode[i]) continue; input_push_analog_dpad(settings->input.binds[i], settings->input.analog_dpad_mode[i]); input_push_analog_dpad(settings->input.autoconf_binds[i], settings->input.analog_dpad_mode[i]); } if ((settings->video.frame_delay > 0) && !input_driver_ctl(RARCH_INPUT_CTL_IS_NONBLOCK_STATE, NULL)) retro_sleep(settings->video.frame_delay); /* Run libretro for one frame. */ core.retro_run(); #ifdef HAVE_CHEEVOS /* Test the achievements. */ cheevos_test(); #endif for (i = 0; i < settings->input.max_users; i++) { if (!settings->input.analog_dpad_mode[i]) continue; input_pop_analog_dpad(settings->input.binds[i]); input_pop_analog_dpad(settings->input.autoconf_binds[i]); } if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL)) bsv_movie_ctl(BSV_MOVIE_CTL_SET_FRAME_END, NULL); #ifdef HAVE_NETPLAY netplay_driver_ctl(RARCH_NETPLAY_CTL_POST_FRAME, NULL); #endif #if defined(HAVE_THREADS) unlock_autosave(); #endif #ifdef HAVE_MENU end: #endif if (!settings->fastforward_ratio) return 0; current = retro_get_time_usec(); target = frame_limit_last_time + frame_limit_minimum_time; to_sleep_ms = (target - current) / 1000; if (to_sleep_ms > 0) { *sleep_ms = (unsigned)to_sleep_ms; /* Combat jitter a bit. */ frame_limit_last_time += frame_limit_minimum_time; return 1; } frame_limit_last_time = retro_get_time_usec(); return 0; }
static void rmenu_render(void) { size_t begin, end, i, j; struct font_params font_parms = {0}; char title[256] = {0}; char title_buf[256] = {0}; char title_msg[64] = {0}; menu_handle_t *menu = menu_driver_get_ptr(); menu_display_t *disp = menu_display_get_ptr(); menu_animation_t *anim = menu_animation_get_ptr(); menu_list_t *menu_list = menu_list_get_ptr(); menu_navigation_t *nav = menu_navigation_get_ptr(); global_t *global = global_get_ptr(); uint64_t frame_count = video_driver_get_frame_count(); size_t entries_end = menu_entries_get_end(); if (!menu) return; if (!render_normal) { render_normal = true; return; } if (menu_entries_needs_refresh() && menu_driver_alive() && !disp->msg_force) return; menu_display_fb_unset_dirty(); anim->is_active = false; anim->label.is_updated = false; if (!menu_list->selection_buf) return; begin = (nav->selection_ptr >= (ENTRIES_HEIGHT / 2)) ? (nav->selection_ptr - (ENTRIES_HEIGHT / 2)) : 0; end = ((nav->selection_ptr + ENTRIES_HEIGHT) <= entries_end) ? nav->selection_ptr + ENTRIES_HEIGHT : entries_end; if (entries_end <= ENTRIES_HEIGHT) begin = 0; if (end - begin > ENTRIES_HEIGHT) end = begin + ENTRIES_HEIGHT; rmenu_render_background(); menu_entries_get_title(title, sizeof(title)); menu_animation_ticker_line(title_buf, RMENU_TERM_WIDTH, frame_count / 15, title, true); font_parms.x = POSITION_EDGE_MIN + POSITION_OFFSET; font_parms.y = POSITION_EDGE_MIN + POSITION_RENDER_OFFSET - (POSITION_OFFSET*2); font_parms.scale = FONT_SIZE_NORMAL; font_parms.color = WHITE; video_driver_set_osd_msg(title_buf, &font_parms, NULL); font_parms.x = POSITION_EDGE_MIN + POSITION_OFFSET; font_parms.y = POSITION_EDGE_MAX - (POSITION_OFFSET*2); font_parms.scale = FONT_SIZE_NORMAL; font_parms.color = WHITE; menu_entries_get_core_title(title_msg, sizeof(title_msg)); video_driver_set_osd_msg(title_msg, &font_parms, NULL); j = 0; for (i = begin; i < end; i++, j++) { char entry_path[PATH_MAX_LENGTH] = {0}; char entry_value[PATH_MAX_LENGTH] = {0}; char message[PATH_MAX_LENGTH] = {0}; char entry_title_buf[PATH_MAX_LENGTH] = {0}; char type_str_buf[PATH_MAX_LENGTH] = {0}; unsigned entry_spacing = menu_entry_get_spacing(i); bool entry_selected = menu_entry_is_currently_selected(i); menu_entry_get_value(i, entry_value, sizeof(entry_value)); menu_entry_get_path(i, entry_path, sizeof(entry_path)); menu_animation_ticker_line(entry_title_buf, RMENU_TERM_WIDTH - (entry_spacing + 1 + 2), frame_count / 15, entry_path, entry_selected); menu_animation_ticker_line(type_str_buf, entry_spacing, frame_count / 15, entry_value, entry_selected); snprintf(message, sizeof(message), "%c %s", entry_selected ? '>' : ' ', entry_title_buf); font_parms.x = POSITION_EDGE_MIN + POSITION_OFFSET; font_parms.y = POSITION_EDGE_MIN + POSITION_RENDER_OFFSET + (POSITION_OFFSET * j); font_parms.scale = FONT_SIZE_NORMAL; font_parms.color = WHITE; video_driver_set_osd_msg(message, &font_parms, NULL); font_parms.x = POSITION_EDGE_CENTER + POSITION_OFFSET; video_driver_set_osd_msg(type_str_buf, &font_parms, NULL); } }
bool menu_display_ctl(enum menu_display_ctl_state state, void *data) { unsigned width, height; menu_framebuf_t *frame_buf = menu_display_fb_get_ptr(); menu_display_t *disp = menu_display_get_ptr(); settings_t *settings = config_get_ptr(); switch (state) { case MENU_DISPLAY_CTL_FONT_BUF: { void **ptr = (void**)data; if (!ptr) return false; *ptr = disp->font.buf; } return true; case MENU_DISPLAY_CTL_SET_FONT_BUF: { void **ptr = (void**)data; if (!ptr) return false; disp->font.buf = *ptr; } return true; case MENU_DISPLAY_CTL_FONT_FB: { uint8_t **ptr = (uint8_t**)data; if (!ptr) return false; *ptr = (uint8_t*)disp->font.framebuf; } return true; case MENU_DISPLAY_CTL_SET_FONT_FB: { uint8_t **ptr = (uint8_t**)data; if (!ptr) return false; disp->font.framebuf = *ptr; } return true; case MENU_DISPLAY_CTL_LIBRETRO_RUNNING: { global_t *global = global_get_ptr(); if (!settings->menu.pause_libretro) if (global->inited.main && (global->inited.core.type != CORE_TYPE_DUMMY)) return true; } break; case MENU_DISPLAY_CTL_LIBRETRO: video_driver_set_texture_enable(true, false); if (menu_display_ctl(MENU_DISPLAY_CTL_LIBRETRO_RUNNING, NULL)) { driver_t *driver = driver_get_ptr(); bool block_libretro_input = driver->block_libretro_input; driver->block_libretro_input = true; core.retro_run(); driver->block_libretro_input = block_libretro_input; return true; } video_driver_cached_frame(); return true; case MENU_DISPLAY_CTL_SET_WIDTH: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; frame_buf->width = *ptr; } return true; case MENU_DISPLAY_CTL_WIDTH: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; *ptr = frame_buf->width; } return true; case MENU_DISPLAY_CTL_HEIGHT: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; *ptr = frame_buf->height; } return true; case MENU_DISPLAY_CTL_HEADER_HEIGHT: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; *ptr = disp->header_height; } return true; case MENU_DISPLAY_CTL_SET_HEADER_HEIGHT: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; disp->header_height = *ptr; } return true; case MENU_DISPLAY_CTL_FONT_SIZE: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; *ptr = disp->font.size; } return true; case MENU_DISPLAY_CTL_SET_FONT_SIZE: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; disp->font.size = *ptr; } return true; case MENU_DISPLAY_CTL_SET_HEIGHT: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; frame_buf->height = *ptr; } return true; case MENU_DISPLAY_CTL_FB_DATA: { uint16_t **ptr = (uint16_t**)data; if (!ptr) return false; *ptr = frame_buf->data; } return true; case MENU_DISPLAY_CTL_SET_FB_DATA: { uint16_t *ptr = (uint16_t*)data; if (!ptr) return false; frame_buf->data = ptr; } return true; case MENU_DISPLAY_CTL_FB_PITCH: { size_t *ptr = (size_t*)data; if (!ptr) return false; *ptr = frame_buf->pitch; } return true; case MENU_DISPLAY_CTL_SET_FB_PITCH: { size_t *ptr = (size_t*)data; if (!ptr) return false; frame_buf->pitch = *ptr; } return true; case MENU_DISPLAY_CTL_MSG_FORCE: { bool *ptr = (bool*)data; if (!ptr) return false; *ptr = disp->msg_force; } return true; case MENU_DISPLAY_CTL_SET_MSG_FORCE: { bool *ptr = (bool*)data; if (!ptr) return false; disp->msg_force = *ptr; } return true; case MENU_DISPLAY_CTL_FONT_DATA_INIT: { bool *ptr = (bool*)data; if (!ptr) return false; *ptr = disp->font.alloc_framebuf; } return true; case MENU_DISPLAY_CTL_SET_FONT_DATA_INIT: { bool *ptr = (bool*)data; if (!ptr) return false; disp->font.alloc_framebuf = *ptr; } return true; case MENU_DISPLAY_CTL_UPDATE_PENDING: { bool ptr; menu_display_ctl(MENU_DISPLAY_CTL_GET_FRAMEBUFFER_DIRTY_FLAG, &ptr); if (menu_animation_ctl(MENU_ANIMATION_CTL_IS_ACTIVE, NULL) || ptr) return true; } return false; case MENU_DISPLAY_CTL_SET_VIEWPORT: video_driver_get_size(&width, &height); video_driver_set_viewport(width, height, true, false); return true; case MENU_DISPLAY_CTL_UNSET_VIEWPORT: video_driver_get_size(&width, &height); video_driver_set_viewport(width, height, false, true); return true; case MENU_DISPLAY_CTL_GET_FRAMEBUFFER_DIRTY_FLAG: { bool *ptr = (bool*)data; if (!ptr || !frame_buf) return false; *ptr = frame_buf->dirty; } return true; case MENU_DISPLAY_CTL_SET_FRAMEBUFFER_DIRTY_FLAG: if (frame_buf && frame_buf->data) frame_buf->dirty = true; return true; case MENU_DISPLAY_CTL_UNSET_FRAMEBUFFER_DIRTY_FLAG: if (frame_buf && frame_buf->data) frame_buf->dirty = false; return true; case MENU_DISPLAY_CTL_GET_DPI: { float *dpi = (float*)data; *dpi = menu_dpi_override_value; if (!settings) return true; if (settings->menu.dpi.override_enable) *dpi = settings->menu.dpi.override_value; else if (!gfx_ctx_get_metrics(DISPLAY_METRIC_DPI, dpi)) *dpi = menu_dpi_override_value; } return true; } return false; }
static int zarch_zui_render_lay_root_load(zui_t *zui, zui_tabbed_t *tabbed) { char parent_dir[PATH_MAX_LENGTH]; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); if (zarch_zui_tab(zui, tabbed, "Load", 1)) { unsigned cwd_offset; if (!zui->load_cwd) zui->load_cwd = strdup(settings->menu_content_directory); if (!zui->load_dlist) { zui->load_dlist = dir_list_new(zui->load_cwd, global->core_info.current->supported_extensions, true, true); dir_list_sort(zui->load_dlist, true); zui->load_dlist_first = 0; } cwd_offset = min(strlen(zui->load_cwd), 60); zarch_zui_draw_text(zui, ZUI_FG_NORMAL, 15, tabbed->tabline_size + 5 + 41, &zui->load_cwd[strlen(zui->load_cwd) - cwd_offset]); if (zarch_zui_button(zui, zui->width - 290 - 129, tabbed->tabline_size + 5, "Home")) zarch_zui_render_lay_root_load_free(zui); if (zui->load_dlist) { fill_pathname_parent_dir(parent_dir, zui->load_cwd, sizeof(parent_dir)); if (parent_dir[0] != '\0' && zarch_zui_list_item(zui, tabbed, 0, tabbed->tabline_size + 73, " ..", 0, NULL /* TODO/FIXME */)) { zarch_zui_render_lay_root_load_set_new_path(zui, parent_dir); } else { unsigned size = zui->load_dlist->size; unsigned i, j = 1; unsigned skip = 0; for (i = 0; i < size; ++i) { const char *basename = path_basename(zui->load_dlist->elems[i].data); if (basename[0] != '.') break; skip++; } zui->load_dlist_first += zui->mouse.wheel; if (zui->load_dlist_first < 0) zui->load_dlist_first = 0; else if (zui->load_dlist_first > size - 5) zui->load_dlist_first = size - 5; zui->load_dlist_first = min(max(zui->load_dlist_first, 0), size - 5 - skip); for (i = skip + zui->load_dlist_first; i < size; ++i) { char label[PATH_MAX_LENGTH]; const char *path = NULL; const char *basename = NULL; if (j > 10) break; path = zui->load_dlist->elems[i].data; basename = path_basename(path); *label = 0; strncat(label, " ", sizeof(label)-1); strncat(label, basename, sizeof(label)-1); if (path_is_directory(path)) strncat(label, "/", sizeof(label)-1); if (zarch_zui_list_item(zui, tabbed, 0, tabbed->tabline_size + 73 + j * 54, label, i, NULL)) { if (path_is_directory(path)) { zarch_zui_render_lay_root_load_set_new_path(zui, path); break; } zui->pick_cores = NULL; zui->pick_supported = 0; strncpy(zui->pick_content, path, sizeof(zui->pick_content)-1); core_info_list_get_supported_cores(global->core_info.list, path, &zui->pick_cores, &zui->pick_supported); layout = LAY_PICK_CORE; break; } j++; } } } } else if (zui->load_dlist) { dir_list_free(zui->load_dlist); zui->load_dlist = NULL; } return 0; }
/** * rarch_main_init: * @argc : Count of (commandline) arguments. * @argv : (Commandline) arguments. * * Initializes the program. * * Returns: 0 on success, otherwise 1 if there was an error. **/ int rarch_main_init(int argc, char *argv[]) { int sjlj_ret; global_t *global = global_get_ptr(); init_state(); if ((sjlj_ret = setjmp(global->error_sjlj_context)) > 0) { RARCH_ERR("Fatal error received in: \"%s\"\n", global->error_string); return sjlj_ret; } global->inited.error = true; global->log_file = stderr; parse_input(argc, argv); if (global->verbosity) { char str[PATH_MAX_LENGTH] = {0}; RARCH_LOG_OUTPUT("=== Build ======================================="); rarch_info_get_capabilities(RARCH_CAPABILITIES_CPU, str, sizeof(str)); fprintf(stderr, "%s", str); fprintf(stderr, "Built: %s\n", __DATE__); RARCH_LOG_OUTPUT("Version: %s\n", PACKAGE_VERSION); #ifdef HAVE_GIT_VERSION RARCH_LOG_OUTPUT("Git: %s\n", rarch_git_version); #endif RARCH_LOG_OUTPUT("=================================================\n"); } rarch_ctl(RARCH_ACTION_STATE_VALIDATE_CPU_FEATURES, NULL); config_load(); { settings_t *settings = config_get_ptr(); if (settings && (settings->multimedia.builtin_mediaplayer_enable || settings->multimedia.builtin_imageviewer_enable)) { switch (rarch_path_is_media_type(global->path.fullpath)) { case RARCH_CONTENT_MOVIE: case RARCH_CONTENT_MUSIC: if (settings->multimedia.builtin_mediaplayer_enable) { #ifdef HAVE_FFMPEG global->has_set.libretro = false; global->inited.core.type = CORE_TYPE_FFMPEG; #endif } break; #ifdef HAVE_IMAGEVIEWER case RARCH_CONTENT_IMAGE: if (settings->multimedia.builtin_imageviewer_enable) { global->has_set.libretro = false; global->inited.core.type = CORE_TYPE_IMAGEVIEWER; } break; #endif default: break; } } } init_libretro_sym(global->inited.core.type); rarch_system_info_init(); init_drivers_pre(); if (!event_command(EVENT_CMD_CORE_INIT)) goto error; event_command(EVENT_CMD_DRIVERS_INIT); event_command(EVENT_CMD_COMMAND_INIT); event_command(EVENT_CMD_REWIND_INIT); event_command(EVENT_CMD_CONTROLLERS_INIT); event_command(EVENT_CMD_RECORD_INIT); event_command(EVENT_CMD_CHEATS_INIT); event_command(EVENT_CMD_REMAPPING_INIT); event_command(EVENT_CMD_SAVEFILES_INIT); #if defined(GEKKO) && defined(HW_RVL) { settings_t *settings = config_get_ptr(); if (settings) { event_command(EVENT_CMD_VIDEO_SET_ASPECT_RATIO); video_driver_set_aspect_ratio(settings->video.aspect_ratio_idx); } unsigned width = 0, height = 0; (void)width; (void)height; width = global->console.screen.resolutions.width; height = global->console.screen.resolutions.height; video_driver_set_video_mode(width, height, true); char msg[PATH_MAX_LENGTH] = {0}; snprintf(msg, sizeof(msg),"Resolution: %dx%d",width, height); rarch_main_msg_queue_push(msg, 1, 100, true); } #endif global->inited.error = false; global->inited.main = true; return 0; error: event_command(EVENT_CMD_CORE_DEINIT); global->inited.main = false; return 1; }
static void menu_action_setting_disp_set_label(file_list_t* list, unsigned *w, unsigned type, unsigned i, const char *label, char *s, size_t len, const char *entry_label, const char *path, char *s2, size_t len2) { rarch_system_info_t *system = rarch_system_info_get_ptr(); uint32_t hash_label = menu_hash_calculate(label); *s = '\0'; *w = 19; switch (hash_label) { case MENU_LABEL_LOAD_CONTENT_HISTORY: *w = strlen(label); break; case MENU_LABEL_SYSTEM_INFORMATION: *w = 2; break; case MENU_LABEL_DEBUG_INFORMATION: *w = 2; break; } if (type >= MENU_SETTINGS_PLAYLIST_ASSOCIATION_START) { char playlist_name_with_ext[PATH_MAX_LENGTH]; unsigned i; bool found_matching_core_association = false; settings_t *settings = config_get_ptr(); struct string_list *str_list = string_split(settings->playlist_names, ";"); struct string_list *str_list2 = string_split(settings->playlist_cores, ";"); strlcpy(playlist_name_with_ext, path, sizeof(playlist_name_with_ext)); strlcat(playlist_name_with_ext, ".lpl", sizeof(playlist_name_with_ext)); for (i = 0; i < str_list->size; i++) { if (!strcmp(str_list->elems[i].data, playlist_name_with_ext)) { if (str_list->size != str_list2->size) break; if (str_list2->elems[i].data == NULL) break; found_matching_core_association = true; strlcpy(s, str_list2->elems[i].data, len); } } string_list_free(str_list); string_list_free(str_list2); if (!strcmp(s, "DETECT") || !found_matching_core_association) strlcpy(s, "N/A", len); else { global_t *global = global_get_ptr(); char buf[PATH_MAX_LENGTH]; if (core_info_list_get_display_name(global->core_info.list, s, buf, sizeof(buf))) strlcpy(s, buf, len); } } else if (type >= MENU_SETTINGS_CORE_OPTION_START) { const char *core_opt = NULL; if (!system) return; core_opt = core_option_get_val(system->core_options, type - MENU_SETTINGS_CORE_OPTION_START); strlcpy(s, core_opt ? core_opt : "", len); } else menu_setting_get_label(list, s, len, w, type, label, entry_label, i); strlcpy(s2, path, len2); }
bool rarch_ctl(enum rarch_ctl_state state, void *data) { driver_t *driver = driver_get_ptr(); global_t *global = global_get_ptr(); settings_t *settings = config_get_ptr(); rarch_system_info_t *system = rarch_system_info_get_ptr(); switch(state) { case RARCH_ACTION_STATE_REPLACE_CONFIG: { char *path = (char*)data; if (!path) return false; /* If config file to be replaced is the same as the * current config file, exit. */ if (!strcmp(path, global->path.config)) return false; if (settings->config_save_on_exit && *global->path.config) config_save_file(global->path.config); strlcpy(global->path.config, path, sizeof(global->path.config)); global->block_config_read = false; *settings->libretro = '\0'; /* Load core in new config. */ } event_command(EVENT_CMD_PREPARE_DUMMY); return true; case RARCH_ACTION_STATE_MENU_RUNNING: #ifdef HAVE_MENU menu_driver_toggle(true); #endif #ifdef HAVE_OVERLAY if (settings->input.overlay_hide_in_menu) event_command(EVENT_CMD_OVERLAY_DEINIT); #endif break; case RARCH_ACTION_STATE_LOAD_CONTENT: #ifdef HAVE_MENU /* If content loading fails, we go back to menu. */ if (!menu_load_content(CORE_TYPE_PLAIN)) rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING, NULL); #endif if (driver->frontend_ctx && driver->frontend_ctx->content_loaded) driver->frontend_ctx->content_loaded(); break; #ifdef HAVE_FFMPEG case RARCH_ACTION_STATE_LOAD_CONTENT_FFMPEG: #ifdef HAVE_MENU /* If content loading fails, we go back to menu. */ if (!menu_load_content(CORE_TYPE_FFMPEG)) rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING, NULL); #endif if (driver->frontend_ctx && driver->frontend_ctx->content_loaded) driver->frontend_ctx->content_loaded(); break; #endif case RARCH_ACTION_STATE_LOAD_CONTENT_IMAGEVIEWER: #ifdef HAVE_MENU /* If content loading fails, we go back to menu. */ if (!menu_load_content(CORE_TYPE_IMAGEVIEWER)) rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING, NULL); #endif if (driver->frontend_ctx && driver->frontend_ctx->content_loaded) driver->frontend_ctx->content_loaded(); break; case RARCH_ACTION_STATE_MENU_RUNNING_FINISHED: #ifdef HAVE_MENU menu_driver_toggle(false); #endif video_driver_set_texture_enable(false, false); #ifdef HAVE_OVERLAY if (settings && settings->input.overlay_hide_in_menu) event_command(EVENT_CMD_OVERLAY_INIT); #endif break; case RARCH_ACTION_STATE_QUIT: if (global) system->shutdown = true; rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING_FINISHED, NULL); break; case RARCH_ACTION_STATE_FORCE_QUIT: rarch_ctl(RARCH_ACTION_STATE_QUIT, NULL); break; case RARCH_ACTION_STATE_VALIDATE_CPU_FEATURES: { uint64_t cpu = retro_get_cpu_features(); (void)cpu; #ifdef __SSE__ if (!(cpu & RETRO_SIMD_SSE)) FAIL_CPU("SSE"); #endif #ifdef __SSE2__ if (!(cpu & RETRO_SIMD_SSE2)) FAIL_CPU("SSE2"); #endif #ifdef __AVX__ if (!(cpu & RETRO_SIMD_AVX)) FAIL_CPU("AVX"); #endif } break; case RARCH_ACTION_STATE_VERIFY_API_VERSION: RARCH_LOG("Version of libretro API: %u\n", core.retro_api_version()); RARCH_LOG("Compiled against API: %u\n", RETRO_API_VERSION); if (core.retro_api_version() != RETRO_API_VERSION) RARCH_WARN("%s\n", msg_hash_to_str(MSG_LIBRETRO_ABI_BREAK)); break; case RARCH_ACTION_STATE_FILL_PATHNAMES: rarch_init_savefile_paths(); strlcpy(global->bsv.movie_path, global->name.savefile, sizeof(global->bsv.movie_path)); if (!*global->name.base) return false; if (!*global->name.ups) fill_pathname_noext(global->name.ups, global->name.base, ".ups", sizeof(global->name.ups)); if (!*global->name.bps) fill_pathname_noext(global->name.bps, global->name.base, ".bps", sizeof(global->name.bps)); if (!*global->name.ips) fill_pathname_noext(global->name.ips, global->name.base, ".ips", sizeof(global->name.ips)); break; case RARCH_ACTION_STATE_NONE: default: return false; } return true; }
static void frontend_psp_get_environment_settings(int *argc, char *argv[], void *args, void *params_data) { struct rarch_main_wrap *params = NULL; (void)args; #ifndef IS_SALAMANDER #if defined(HAVE_LOGGER) logger_init(); #elif defined(HAVE_FILE_LOGGER) #ifndef VITA global_t *global = global_get_ptr(); global->log_file = fopen("ms0:/retroarch-log.txt", "w"); #endif #endif #endif #ifdef VITA strlcpy(eboot_path, "cache0:/retroarch/", sizeof(eboot_path)); strlcpy(g_defaults.dir.port, eboot_path, sizeof(g_defaults.dir.port)); #else strlcpy(eboot_path, argv[0], sizeof(eboot_path)); fill_pathname_basedir(g_defaults.dir.port, argv[0], sizeof(g_defaults.dir.port)); #endif RARCH_LOG("port dir: [%s]\n", g_defaults.dir.port); fill_pathname_join(g_defaults.dir.core_assets, g_defaults.dir.port, "downloads", sizeof(g_defaults.dir.core_assets)); fill_pathname_join(g_defaults.dir.assets, g_defaults.dir.port, "media", sizeof(g_defaults.dir.assets)); fill_pathname_join(g_defaults.dir.core, g_defaults.dir.port, "cores", sizeof(g_defaults.dir.core)); fill_pathname_join(g_defaults.dir.core_info, g_defaults.dir.port, "cores", sizeof(g_defaults.dir.core_info)); fill_pathname_join(g_defaults.dir.savestate, g_defaults.dir.core, "savestates", sizeof(g_defaults.dir.savestate)); fill_pathname_join(g_defaults.dir.sram, g_defaults.dir.core, "savefiles", sizeof(g_defaults.dir.sram)); fill_pathname_join(g_defaults.dir.system, g_defaults.dir.core, "system", sizeof(g_defaults.dir.system)); fill_pathname_join(g_defaults.dir.playlist, g_defaults.dir.core, "playlists", sizeof(g_defaults.dir.playlist)); fill_pathname_join(g_defaults.path.config, g_defaults.dir.port, "retroarch.cfg", sizeof(g_defaults.path.config)); fill_pathname_join(g_defaults.dir.cheats, g_defaults.dir.port, "cheats", sizeof(g_defaults.dir.cheats)); fill_pathname_join(g_defaults.dir.remap, g_defaults.dir.port, "remaps", sizeof(g_defaults.dir.remap)); #ifdef VITA fill_pathname_join(g_defaults.dir.overlay, g_defaults.dir.core, "overlays", sizeof(g_defaults.dir.overlay)); #endif #ifdef VITA params = (struct rarch_main_wrap*)params_data; params->verbose = true; #endif #ifndef IS_SALAMANDER if (argv[1] && (argv[1][0] != '\0')) { static char path[PATH_MAX_LENGTH]; struct rarch_main_wrap *args = NULL; *path = '\0'; args = (struct rarch_main_wrap*)params_data; if (args) { strlcpy(path, argv[1], sizeof(path)); args->touched = true; args->no_content = false; args->verbose = false; args->config_path = NULL; args->sram_path = NULL; args->state_path = NULL; args->content_path = path; args->libretro_path = NULL; RARCH_LOG("argv[0]: %s\n", argv[0]); RARCH_LOG("argv[1]: %s\n", argv[1]); RARCH_LOG("argv[2]: %s\n", argv[2]); RARCH_LOG("Auto-start game %s.\n", argv[1]); } } #endif }
/** * parse_input: * @argc : Count of (commandline) arguments. * @argv : (Commandline) arguments. * * Parses (commandline) arguments passed to program. * **/ static void parse_input(int argc, char *argv[]) { const char *optstring = NULL; global_t *global = global_get_ptr(); settings_t *settings = config_get_ptr(); const struct option opts[] = { #ifdef HAVE_DYNAMIC { "libretro", 1, NULL, 'L' }, #endif { "menu", 0, NULL, RA_OPT_MENU }, { "help", 0, NULL, 'h' }, { "save", 1, NULL, 's' }, { "fullscreen", 0, NULL, 'f' }, { "record", 1, NULL, 'r' }, { "recordconfig", 1, NULL, RA_OPT_RECORDCONFIG }, { "size", 1, NULL, RA_OPT_SIZE }, { "verbose", 0, NULL, 'v' }, { "config", 1, NULL, 'c' }, { "appendconfig", 1, NULL, RA_OPT_APPENDCONFIG }, { "nodevice", 1, NULL, 'N' }, { "dualanalog", 1, NULL, 'A' }, { "device", 1, NULL, 'd' }, { "savestate", 1, NULL, 'S' }, { "bsvplay", 1, NULL, 'P' }, { "bsvrecord", 1, NULL, 'R' }, { "sram-mode", 1, NULL, 'M' }, #ifdef HAVE_NETPLAY { "host", 0, NULL, 'H' }, { "connect", 1, NULL, 'C' }, { "frames", 1, NULL, 'F' }, { "port", 1, NULL, RA_OPT_PORT }, { "spectate", 0, NULL, RA_OPT_SPECTATE }, #endif { "nick", 1, NULL, RA_OPT_NICK }, #if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY) { "command", 1, NULL, RA_OPT_COMMAND }, #endif { "ups", 1, NULL, 'U' }, { "bps", 1, NULL, RA_OPT_BPS }, { "ips", 1, NULL, RA_OPT_IPS }, { "no-patch", 0, NULL, RA_OPT_NO_PATCH }, { "detach", 0, NULL, 'D' }, { "features", 0, NULL, RA_OPT_FEATURES }, { "subsystem", 1, NULL, RA_OPT_SUBSYSTEM }, { "max-frames", 1, NULL, RA_OPT_MAX_FRAMES }, { "eof-exit", 0, NULL, RA_OPT_EOF_EXIT }, { "version", 0, NULL, RA_OPT_VERSION }, #ifdef HAVE_FILE_LOGGER { "log-file", 1, NULL, RA_OPT_LOG_FILE }, #endif { NULL, 0, NULL, 0 } }; global->inited.core.no_content = false; global->inited.core.type = CORE_TYPE_PLAIN; *global->subsystem = '\0'; global->has_set.save_path = false; global->has_set.state_path = false; global->has_set.libretro = false; global->has_set.libretro_directory = false; global->has_set.verbosity = false; global->has_set.netplay_mode = false; global->has_set.username = false; global->has_set.netplay_ip_address = false; global->has_set.netplay_delay_frames = false; global->has_set.netplay_ip_port = false; global->has_set.ups_pref = false; global->has_set.bps_pref = false; global->has_set.ips_pref = false; global->patch.ups_pref = false; global->patch.bps_pref = false; global->patch.ips_pref = false; *global->name.ups = '\0'; *global->name.bps = '\0'; *global->name.ips = '\0'; global->overrides_active = false; if (argc < 2) { global->inited.core.type = CORE_TYPE_DUMMY; return; } /* Make sure we can call parse_input several times ... */ optind = 0; optstring = "hs:fvS:A:c:U:DN:d:" BSV_MOVIE_ARG NETPLAY_ARG DYNAMIC_ARG FFMPEG_RECORD_ARG; for (;;) { int port; int c = getopt_long(argc, argv, optstring, opts, NULL); if (c == -1) break; switch (c) { case 'h': print_help(argv[0]); exit(0); case 'd': { unsigned id = 0; struct string_list *list = string_split(optarg, ":"); port = 0; if (list && list->size == 2) { port = strtol(list->elems[0].data, NULL, 0); id = strtoul(list->elems[1].data, NULL, 0); } string_list_free(list); if (port < 1 || port > MAX_USERS) { RARCH_ERR("Connect device to a valid port.\n"); print_help(argv[0]); rarch_fail(1, "parse_input()"); } settings->input.libretro_device[port - 1] = id; global->has_set.libretro_device[port - 1] = true; break; } case 'A': port = strtol(optarg, NULL, 0); if (port < 1 || port > MAX_USERS) { RARCH_ERR("Connect dualanalog to a valid port.\n"); print_help(argv[0]); rarch_fail(1, "parse_input()"); } settings->input.libretro_device[port - 1] = RETRO_DEVICE_ANALOG; global->has_set.libretro_device[port - 1] = true; break; case 's': strlcpy(global->name.savefile, optarg, sizeof(global->name.savefile)); global->has_set.save_path = true; break; case 'f': global->force_fullscreen = true; break; case 'S': strlcpy(global->name.savestate, optarg, sizeof(global->name.savestate)); global->has_set.state_path = true; break; case 'v': global->verbosity = true; global->has_set.verbosity = true; break; case 'N': port = strtol(optarg, NULL, 0); if (port < 1 || port > MAX_USERS) { RARCH_ERR("Disconnect device from a valid port.\n"); print_help(argv[0]); rarch_fail(1, "parse_input()"); } settings->input.libretro_device[port - 1] = RETRO_DEVICE_NONE; global->has_set.libretro_device[port - 1] = true; break; case 'c': strlcpy(global->path.config, optarg, sizeof(global->path.config)); break; case 'r': strlcpy(global->record.path, optarg, sizeof(global->record.path)); global->record.enable = true; break; #ifdef HAVE_DYNAMIC case 'L': if (path_is_directory(optarg)) { *settings->libretro = '\0'; strlcpy(settings->libretro_directory, optarg, sizeof(settings->libretro_directory)); global->has_set.libretro = true; global->has_set.libretro_directory = true; RARCH_WARN("Using old --libretro behavior. Setting libretro_directory to \"%s\" instead.\n", optarg); } else { strlcpy(settings->libretro, optarg, sizeof(settings->libretro)); global->has_set.libretro = true; } break; #endif case 'P': case 'R': strlcpy(global->bsv.movie_start_path, optarg, sizeof(global->bsv.movie_start_path)); global->bsv.movie_start_playback = (c == 'P'); global->bsv.movie_start_recording = (c == 'R'); break; case 'M': if (!strcmp(optarg, "noload-nosave")) { global->sram.load_disable = true; global->sram.save_disable = true; } else if (!strcmp(optarg, "noload-save")) global->sram.load_disable = true; else if (!strcmp(optarg, "load-nosave")) global->sram.save_disable = true; else if (strcmp(optarg, "load-save") != 0) { RARCH_ERR("Invalid argument in --sram-mode.\n"); print_help(argv[0]); rarch_fail(1, "parse_input()"); } break; #ifdef HAVE_NETPLAY case 'H': global->has_set.netplay_ip_address = true; global->netplay.enable = true; *global->netplay.server = '\0'; break; case 'C': global->has_set.netplay_ip_address = true; global->netplay.enable = true; strlcpy(global->netplay.server, optarg, sizeof(global->netplay.server)); break; case 'F': global->netplay.sync_frames = strtol(optarg, NULL, 0); global->has_set.netplay_delay_frames = true; break; #endif case RA_OPT_BPS: strlcpy(global->name.bps, optarg, sizeof(global->name.bps)); global->patch.bps_pref = true; global->has_set.bps_pref = true; break; case 'U': strlcpy(global->name.ups, optarg, sizeof(global->name.ups)); global->patch.ups_pref = true; global->has_set.ups_pref = true; break; case RA_OPT_IPS: strlcpy(global->name.ips, optarg, sizeof(global->name.ips)); global->patch.ips_pref = true; global->has_set.ips_pref = true; break; case RA_OPT_NO_PATCH: global->patch.block_patch = true; break; case 'D': #if defined(_WIN32) && !defined(_XBOX) FreeConsole(); #endif break; case RA_OPT_MENU: global->inited.core.type = CORE_TYPE_DUMMY; break; #ifdef HAVE_NETPLAY case RA_OPT_PORT: global->has_set.netplay_ip_port = true; global->netplay.port = strtoul(optarg, NULL, 0); break; case RA_OPT_SPECTATE: global->has_set.netplay_mode = true; global->netplay.is_spectate = true; break; #endif case RA_OPT_NICK: global->has_set.username = true; strlcpy(settings->username, optarg, sizeof(settings->username)); break; #if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY) case RA_OPT_COMMAND: if (network_cmd_send(optarg)) exit(0); else rarch_fail(1, "network_cmd_send()"); break; #endif case RA_OPT_APPENDCONFIG: strlcpy(global->path.append_config, optarg, sizeof(global->path.append_config)); break; case RA_OPT_SIZE: { if (sscanf(optarg, "%ux%u", &global->record.width, &global->record.height) != 2) { RARCH_ERR("Wrong format for --size.\n"); print_help(argv[0]); rarch_fail(1, "parse_input()"); } break; } case RA_OPT_RECORDCONFIG: strlcpy(global->record.config, optarg, sizeof(global->record.config)); break; case RA_OPT_MAX_FRAMES: { unsigned max_frames = strtoul(optarg, NULL, 10); rarch_main_ctl(RARCH_MAIN_CTL_SET_MAX_FRAMES, &max_frames); } break; case RA_OPT_SUBSYSTEM: strlcpy(global->subsystem, optarg, sizeof(global->subsystem)); break; case RA_OPT_FEATURES: print_features(); exit(0); case RA_OPT_EOF_EXIT: global->bsv.eof_exit = true; break; case RA_OPT_VERSION: print_version(); exit(0); #ifdef HAVE_FILE_LOGGER case RA_OPT_LOG_FILE: global->log_file = fopen(optarg, "wb"); break; #endif case '?': print_help(argv[0]); rarch_fail(1, "parse_input()"); default: RARCH_ERR("Error parsing arguments.\n"); rarch_fail(1, "parse_input()"); } } if (global->inited.core.type == CORE_TYPE_DUMMY) { if (optind < argc) { RARCH_ERR("--menu was used, but content file was passed as well.\n"); rarch_fail(1, "parse_input()"); } } else if (!*global->subsystem && optind < argc) rarch_set_paths(argv[optind]); else if (*global->subsystem && optind < argc) set_special_paths(argv + optind, argc - optind); else global->inited.core.no_content = true; /* Copy SRM/state dirs used, so they can be reused on reentrancy. */ if (global->has_set.save_path && path_is_directory(global->name.savefile)) strlcpy(global->dir.savefile, global->name.savefile, sizeof(global->dir.savefile)); if (global->has_set.state_path && path_is_directory(global->name.savestate)) strlcpy(global->dir.savestate, global->name.savestate, sizeof(global->dir.savestate)); }
/** * event_cmd_ctl: * @cmd : Event command index. * * Performs program event command with index @cmd. * * Returns: true (1) on success, otherwise false (0). **/ bool event_cmd_ctl(enum event_command cmd, void *data) { unsigned i = 0; bool boolean = false; settings_t *settings = config_get_ptr(); rarch_system_info_t *info = NULL; runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &info); (void)i; switch (cmd) { case EVENT_CMD_MENU_REFRESH: #ifdef HAVE_MENU menu_driver_ctl(RARCH_MENU_CTL_REFRESH, NULL); #endif break; case EVENT_CMD_SET_PER_GAME_RESOLUTION: #if defined(GEKKO) { unsigned width = 0, height = 0; event_cmd_ctl(EVENT_CMD_VIDEO_SET_ASPECT_RATIO, NULL); if (video_driver_get_video_output_size(&width, &height)) { char msg[128] = {0}; video_driver_set_video_mode(width, height, true); if (width == 0 || height == 0) strlcpy(msg, "Resolution: DEFAULT", sizeof(msg)); else snprintf(msg, sizeof(msg),"Resolution: %dx%d",width, height); runloop_msg_queue_push(msg, 1, 100, true); } } #endif break; case EVENT_CMD_LOAD_CONTENT_PERSIST: #ifdef HAVE_DYNAMIC event_cmd_ctl(EVENT_CMD_LOAD_CORE, NULL); #endif rarch_ctl(RARCH_CTL_LOAD_CONTENT, NULL); break; #ifdef HAVE_FFMPEG case EVENT_CMD_LOAD_CONTENT_FFMPEG: rarch_ctl(RARCH_CTL_LOAD_CONTENT_FFMPEG, NULL); break; #endif case EVENT_CMD_LOAD_CONTENT_IMAGEVIEWER: rarch_ctl(RARCH_CTL_LOAD_CONTENT_IMAGEVIEWER, NULL); break; case EVENT_CMD_LOAD_CONTENT: { #ifdef HAVE_DYNAMIC event_cmd_ctl(EVENT_CMD_LOAD_CONTENT_PERSIST, NULL); #else char *fullpath = NULL; runloop_ctl(RUNLOOP_CTL_GET_CONTENT_PATH, &fullpath); runloop_ctl(RUNLOOP_CTL_SET_LIBRETRO_PATH, settings->libretro); event_cmd_ctl(EVENT_CMD_EXEC, (void*)fullpath); event_cmd_ctl(EVENT_CMD_QUIT, NULL); #endif } break; case EVENT_CMD_LOAD_CORE_DEINIT: #ifdef HAVE_MENU menu_driver_ctl(RARCH_MENU_CTL_SYSTEM_INFO_DEINIT, NULL); #endif break; case EVENT_CMD_LOAD_CORE_PERSIST: event_cmd_ctl(EVENT_CMD_LOAD_CORE_DEINIT, NULL); { #ifdef HAVE_MENU bool *ptr = NULL; struct retro_system_info *system = NULL; menu_driver_ctl(RARCH_MENU_CTL_SYSTEM_INFO_GET, &system); if (menu_driver_ctl(RARCH_MENU_CTL_LOAD_NO_CONTENT_GET, &ptr)) { core_info_ctx_find_t info_find; #if defined(HAVE_DYNAMIC) if (!(*settings->libretro)) return false; libretro_get_system_info(settings->libretro, system, ptr); #endif info_find.path = settings->libretro; if (!core_info_ctl(CORE_INFO_CTL_LOAD, &info_find)) return false; } #endif } break; case EVENT_CMD_LOAD_CORE: event_cmd_ctl(EVENT_CMD_LOAD_CORE_PERSIST, NULL); #ifndef HAVE_DYNAMIC event_cmd_ctl(EVENT_CMD_QUIT, NULL); #endif break; case EVENT_CMD_LOAD_STATE: /* Immutable - disallow savestate load when * we absolutely cannot change game state. */ if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL)) return false; #ifdef HAVE_NETPLAY if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL)) return false; #endif #ifdef HAVE_CHEEVOS if (settings->cheevos.hardcore_mode_enable) return false; #endif event_main_state(cmd); break; case EVENT_CMD_RESIZE_WINDOWED_SCALE: { unsigned idx = 0; unsigned *window_scale = NULL; runloop_ctl(RUNLOOP_CTL_GET_WINDOWED_SCALE, &window_scale); if (*window_scale == 0) return false; settings->video.scale = *window_scale; if (!settings->video.fullscreen) event_cmd_ctl(EVENT_CMD_REINIT, NULL); runloop_ctl(RUNLOOP_CTL_SET_WINDOWED_SCALE, &idx); } break; case EVENT_CMD_MENU_TOGGLE: #ifdef HAVE_MENU if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); else rarch_ctl(RARCH_CTL_MENU_RUNNING, NULL); #endif break; case EVENT_CMD_CONTROLLERS_INIT: event_init_controllers(); break; case EVENT_CMD_RESET: RARCH_LOG("%s.\n", msg_hash_to_str(MSG_RESET)); runloop_msg_queue_push(msg_hash_to_str(MSG_RESET), 1, 120, true); #ifdef HAVE_CHEEVOS cheevos_ctl(CHEEVOS_CTL_SET_CHEATS, NULL); #endif core_ctl(CORE_CTL_RETRO_RESET, NULL); break; case EVENT_CMD_SAVE_STATE: #ifdef HAVE_CHEEVOS if (settings->cheevos.hardcore_mode_enable) return false; #endif if (settings->savestate_auto_index) settings->state_slot++; event_main_state(cmd); break; case EVENT_CMD_SAVE_STATE_DECREMENT: /* Slot -1 is (auto) slot. */ if (settings->state_slot >= 0) settings->state_slot--; break; case EVENT_CMD_SAVE_STATE_INCREMENT: settings->state_slot++; break; case EVENT_CMD_TAKE_SCREENSHOT: if (!take_screenshot()) return false; break; case EVENT_CMD_UNLOAD_CORE: runloop_ctl(RUNLOOP_CTL_PREPARE_DUMMY, NULL); event_cmd_ctl(EVENT_CMD_LOAD_CORE_DEINIT, NULL); break; case EVENT_CMD_QUIT: rarch_ctl(RARCH_CTL_QUIT, NULL); break; case EVENT_CMD_CHEEVOS_HARDCORE_MODE_TOGGLE: #ifdef HAVE_CHEEVOS cheevos_ctl(CHEEVOS_CTL_TOGGLE_HARDCORE_MODE, NULL); #endif break; case EVENT_CMD_REINIT: { struct retro_hw_render_callback *hwr = NULL; video_driver_ctl(RARCH_DISPLAY_CTL_HW_CONTEXT_GET, &hwr); if (hwr->cache_context) video_driver_ctl( RARCH_DISPLAY_CTL_SET_VIDEO_CACHE_CONTEXT, NULL); else video_driver_ctl( RARCH_DISPLAY_CTL_UNSET_VIDEO_CACHE_CONTEXT, NULL); video_driver_ctl( RARCH_DISPLAY_CTL_UNSET_VIDEO_CACHE_CONTEXT_ACK, NULL); event_cmd_ctl(EVENT_CMD_RESET_CONTEXT, NULL); video_driver_ctl( RARCH_DISPLAY_CTL_UNSET_VIDEO_CACHE_CONTEXT, NULL); /* Poll input to avoid possibly stale data to corrupt things. */ input_driver_ctl(RARCH_INPUT_CTL_POLL, NULL); #ifdef HAVE_MENU menu_display_ctl( MENU_DISPLAY_CTL_SET_FRAMEBUFFER_DIRTY_FLAG, NULL); if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) event_cmd_ctl(EVENT_CMD_VIDEO_SET_BLOCKING_STATE, NULL); #endif } break; case EVENT_CMD_CHEATS_DEINIT: cheat_manager_state_free(); break; case EVENT_CMD_CHEATS_INIT: event_cmd_ctl(EVENT_CMD_CHEATS_DEINIT, NULL); event_init_cheats(); break; case EVENT_CMD_CHEATS_APPLY: cheat_manager_apply_cheats(); break; case EVENT_CMD_REWIND_DEINIT: #ifdef HAVE_NETPLAY if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL)) return false; #endif #ifdef HAVE_CHEEVOS if (settings->cheevos.hardcore_mode_enable) return false; #endif state_manager_event_deinit(); break; case EVENT_CMD_REWIND_INIT: #ifdef HAVE_CHEEVOS if (settings->cheevos.hardcore_mode_enable) return false; #endif #ifdef HAVE_NETPLAY if (!netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL)) #endif init_rewind(); break; case EVENT_CMD_REWIND_TOGGLE: if (settings->rewind_enable) event_cmd_ctl(EVENT_CMD_REWIND_INIT, NULL); else event_cmd_ctl(EVENT_CMD_REWIND_DEINIT, NULL); break; case EVENT_CMD_AUTOSAVE_DEINIT: #ifdef HAVE_THREADS autosave_event_deinit(); #endif break; case EVENT_CMD_AUTOSAVE_INIT: event_cmd_ctl(EVENT_CMD_AUTOSAVE_DEINIT, NULL); #ifdef HAVE_THREADS autosave_event_init(); #endif break; case EVENT_CMD_AUTOSAVE_STATE: event_save_auto_state(); break; case EVENT_CMD_AUDIO_STOP: if (!audio_driver_ctl(RARCH_AUDIO_CTL_ALIVE, NULL)) return false; if (!audio_driver_ctl(RARCH_AUDIO_CTL_STOP, NULL)) return false; break; case EVENT_CMD_AUDIO_START: if (audio_driver_ctl(RARCH_AUDIO_CTL_ALIVE, NULL)) return false; if (!settings->audio.mute_enable && !audio_driver_ctl(RARCH_AUDIO_CTL_START, NULL)) { RARCH_ERR("Failed to start audio driver. " "Will continue without audio.\n"); audio_driver_ctl(RARCH_AUDIO_CTL_UNSET_ACTIVE, NULL); } break; case EVENT_CMD_AUDIO_MUTE_TOGGLE: { const char *msg = !settings->audio.mute_enable ? msg_hash_to_str(MSG_AUDIO_MUTED): msg_hash_to_str(MSG_AUDIO_UNMUTED); if (!audio_driver_ctl(RARCH_AUDIO_CTL_MUTE_TOGGLE, NULL)) { RARCH_ERR("%s.\n", msg_hash_to_str(MSG_FAILED_TO_UNMUTE_AUDIO)); return false; } runloop_msg_queue_push(msg, 1, 180, true); RARCH_LOG("%s\n", msg); } break; case EVENT_CMD_OVERLAY_DEINIT: #ifdef HAVE_OVERLAY input_overlay_free(); #endif break; case EVENT_CMD_OVERLAY_INIT: event_cmd_ctl(EVENT_CMD_OVERLAY_DEINIT, NULL); #ifdef HAVE_OVERLAY input_overlay_init(); #endif break; case EVENT_CMD_OVERLAY_NEXT: #ifdef HAVE_OVERLAY input_overlay_next(settings->input.overlay_opacity); #endif break; case EVENT_CMD_DSP_FILTER_DEINIT: audio_driver_dsp_filter_free(); break; case EVENT_CMD_DSP_FILTER_INIT: event_cmd_ctl(EVENT_CMD_DSP_FILTER_DEINIT, NULL); if (!*settings->audio.dsp_plugin) break; audio_driver_dsp_filter_init(settings->audio.dsp_plugin); break; case EVENT_CMD_GPU_RECORD_DEINIT: video_driver_ctl(RARCH_DISPLAY_CTL_GPU_RECORD_DEINIT, NULL); break; case EVENT_CMD_RECORD_DEINIT: if (!recording_deinit()) return false; break; case EVENT_CMD_RECORD_INIT: event_cmd_ctl(EVENT_CMD_HISTORY_DEINIT, NULL); if (!recording_init()) return false; break; case EVENT_CMD_HISTORY_DEINIT: if (g_defaults.history) { content_playlist_write_file(g_defaults.history); content_playlist_free(g_defaults.history); } g_defaults.history = NULL; break; case EVENT_CMD_HISTORY_INIT: event_cmd_ctl(EVENT_CMD_HISTORY_DEINIT, NULL); if (!settings->history_list_enable) return false; RARCH_LOG("%s: [%s].\n", msg_hash_to_str(MSG_LOADING_HISTORY_FILE), settings->content_history_path); g_defaults.history = content_playlist_init( settings->content_history_path, settings->content_history_size); break; case EVENT_CMD_CORE_INFO_DEINIT: core_info_ctl(CORE_INFO_CTL_LIST_DEINIT, NULL); break; case EVENT_CMD_CORE_INFO_INIT: event_cmd_ctl(EVENT_CMD_CORE_INFO_DEINIT, NULL); if (*settings->libretro_directory) core_info_ctl(CORE_INFO_CTL_LIST_INIT, NULL); break; case EVENT_CMD_CORE_DEINIT: { struct retro_hw_render_callback *hwr = NULL; video_driver_ctl(RARCH_DISPLAY_CTL_HW_CONTEXT_GET, &hwr); event_deinit_core(true); if (hwr) memset(hwr, 0, sizeof(*hwr)); break; } case EVENT_CMD_CORE_INIT: if (!event_init_core(data)) return false; break; case EVENT_CMD_VIDEO_APPLY_STATE_CHANGES: video_driver_ctl(RARCH_DISPLAY_CTL_APPLY_STATE_CHANGES, NULL); break; case EVENT_CMD_VIDEO_SET_NONBLOCKING_STATE: boolean = true; /* fall-through */ case EVENT_CMD_VIDEO_SET_BLOCKING_STATE: video_driver_ctl(RARCH_DISPLAY_CTL_SET_NONBLOCK_STATE, &boolean); break; case EVENT_CMD_VIDEO_SET_ASPECT_RATIO: video_driver_ctl(RARCH_DISPLAY_CTL_SET_ASPECT_RATIO, NULL); break; case EVENT_CMD_AUDIO_SET_NONBLOCKING_STATE: boolean = true; /* fall-through */ case EVENT_CMD_AUDIO_SET_BLOCKING_STATE: audio_driver_set_nonblocking_state(boolean); break; case EVENT_CMD_OVERLAY_SET_SCALE_FACTOR: #ifdef HAVE_OVERLAY input_overlay_set_scale_factor(settings->input.overlay_scale); #endif break; case EVENT_CMD_OVERLAY_SET_ALPHA_MOD: #ifdef HAVE_OVERLAY input_overlay_set_alpha_mod(settings->input.overlay_opacity); #endif break; case EVENT_CMD_AUDIO_REINIT: { int flags = DRIVER_AUDIO; driver_ctl(RARCH_DRIVER_CTL_UNINIT, &flags); driver_ctl(RARCH_DRIVER_CTL_INIT, &flags); } break; case EVENT_CMD_RESET_CONTEXT: { /* RARCH_DRIVER_CTL_UNINIT clears the callback struct so we * need to make sure to keep a copy */ struct retro_hw_render_callback *hwr = NULL; struct retro_hw_render_callback hwr_copy; int flags = DRIVERS_CMD_ALL; video_driver_ctl(RARCH_DISPLAY_CTL_HW_CONTEXT_GET, &hwr); memcpy(&hwr_copy, hwr, sizeof(hwr_copy)); driver_ctl(RARCH_DRIVER_CTL_UNINIT, &flags); memcpy(hwr, &hwr_copy, sizeof(*hwr)); driver_ctl(RARCH_DRIVER_CTL_INIT, &flags); } break; case EVENT_CMD_QUIT_RETROARCH: rarch_ctl(RARCH_CTL_FORCE_QUIT, NULL); break; case EVENT_CMD_SHUTDOWN: #if defined(__linux__) && !defined(ANDROID) runloop_msg_queue_push("Shutting down...", 1, 180, true); rarch_ctl(RARCH_CTL_FORCE_QUIT, NULL); system("shutdown -P now"); #endif break; case EVENT_CMD_REBOOT: #if defined(__linux__) && !defined(ANDROID) runloop_msg_queue_push("Rebooting...", 1, 180, true); rarch_ctl(RARCH_CTL_FORCE_QUIT, NULL); system("shutdown -r now"); #endif break; case EVENT_CMD_RESUME: rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); if (ui_companion_is_on_foreground()) ui_companion_driver_toggle(); break; case EVENT_CMD_RESTART_RETROARCH: if (!frontend_driver_set_fork(FRONTEND_FORK_RESTART)) return false; break; case EVENT_CMD_MENU_SAVE_CURRENT_CONFIG: event_save_current_config(); break; case EVENT_CMD_MENU_SAVE_CONFIG: if (!event_save_core_config()) return false; break; case EVENT_CMD_SHADERS_APPLY_CHANGES: #ifdef HAVE_MENU menu_shader_manager_apply_changes(); #endif break; case EVENT_CMD_PAUSE_CHECKS: if (runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL)) { RARCH_LOG("%s\n", msg_hash_to_str(MSG_PAUSED)); event_cmd_ctl(EVENT_CMD_AUDIO_STOP, NULL); if (settings->video.black_frame_insertion) video_driver_ctl(RARCH_DISPLAY_CTL_CACHED_FRAME_RENDER, NULL); } else { RARCH_LOG("%s\n", msg_hash_to_str(MSG_UNPAUSED)); event_cmd_ctl(EVENT_CMD_AUDIO_START, NULL); } break; case EVENT_CMD_PAUSE_TOGGLE: boolean = runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL); boolean = !boolean; runloop_ctl(RUNLOOP_CTL_SET_PAUSED, &boolean); event_cmd_ctl(EVENT_CMD_PAUSE_CHECKS, NULL); break; case EVENT_CMD_UNPAUSE: boolean = false; runloop_ctl(RUNLOOP_CTL_SET_PAUSED, &boolean); event_cmd_ctl(EVENT_CMD_PAUSE_CHECKS, NULL); break; case EVENT_CMD_PAUSE: boolean = true; runloop_ctl(RUNLOOP_CTL_SET_PAUSED, &boolean); event_cmd_ctl(EVENT_CMD_PAUSE_CHECKS, NULL); break; case EVENT_CMD_MENU_PAUSE_LIBRETRO: #ifdef HAVE_MENU if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) { if (settings->menu.pause_libretro) event_cmd_ctl(EVENT_CMD_AUDIO_STOP, NULL); else event_cmd_ctl(EVENT_CMD_AUDIO_START, NULL); } else { if (settings->menu.pause_libretro) event_cmd_ctl(EVENT_CMD_AUDIO_START, NULL); } #endif break; case EVENT_CMD_SHADER_DIR_DEINIT: runloop_ctl(RUNLOOP_CTL_SHADER_DIR_DEINIT, NULL); break; case EVENT_CMD_SHADER_DIR_INIT: event_cmd_ctl(EVENT_CMD_SHADER_DIR_DEINIT, NULL); if (!runloop_ctl(RUNLOOP_CTL_SHADER_DIR_INIT, NULL)) return false; break; case EVENT_CMD_SAVEFILES: { global_t *global = global_get_ptr(); if (!global->savefiles || !global->sram.use) return false; for (i = 0; i < global->savefiles->size; i++) { ram_type_t ram; ram.type = global->savefiles->elems[i].attr.i; ram.path = global->savefiles->elems[i].data; RARCH_LOG("%s #%u %s \"%s\".\n", msg_hash_to_str(MSG_SAVING_RAM_TYPE), ram.type, msg_hash_to_str(MSG_TO), ram.path); content_ctl(CONTENT_CTL_SAVE_RAM_FILE, &ram); } } return true; case EVENT_CMD_SAVEFILES_DEINIT: { global_t *global = global_get_ptr(); if (!global) break; if (global->savefiles) string_list_free(global->savefiles); global->savefiles = NULL; } break; case EVENT_CMD_SAVEFILES_INIT: { global_t *global = global_get_ptr(); global->sram.use = global->sram.use && !global->sram.save_disable; #ifdef HAVE_NETPLAY global->sram.use = global->sram.use && (!netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL) || !global->netplay.is_client); #endif if (!global->sram.use) RARCH_LOG("%s\n", msg_hash_to_str(MSG_SRAM_WILL_NOT_BE_SAVED)); if (global->sram.use) event_cmd_ctl(EVENT_CMD_AUTOSAVE_INIT, NULL); } break; case EVENT_CMD_BSV_MOVIE_DEINIT: bsv_movie_ctl(BSV_MOVIE_CTL_DEINIT, NULL); break; case EVENT_CMD_BSV_MOVIE_INIT: event_cmd_ctl(EVENT_CMD_BSV_MOVIE_DEINIT, NULL); bsv_movie_ctl(BSV_MOVIE_CTL_INIT, NULL); break; case EVENT_CMD_NETPLAY_DEINIT: #ifdef HAVE_NETPLAY deinit_netplay(); #endif break; case EVENT_CMD_NETWORK_DEINIT: #ifdef HAVE_NETWORKING network_deinit(); #endif break; case EVENT_CMD_NETWORK_INIT: #ifdef HAVE_NETWORKING network_init(); #endif break; case EVENT_CMD_NETPLAY_INIT: event_cmd_ctl(EVENT_CMD_NETPLAY_DEINIT, NULL); #ifdef HAVE_NETPLAY if (!init_netplay()) return false; #endif break; case EVENT_CMD_NETPLAY_FLIP_PLAYERS: #ifdef HAVE_NETPLAY netplay_driver_ctl(RARCH_NETPLAY_CTL_FLIP_PLAYERS, NULL); #endif break; case EVENT_CMD_FULLSCREEN_TOGGLE: if (!video_driver_ctl(RARCH_DISPLAY_CTL_HAS_WINDOWED, NULL)) return false; /* If we go fullscreen we drop all drivers and * reinitialize to be safe. */ settings->video.fullscreen = !settings->video.fullscreen; event_cmd_ctl(EVENT_CMD_REINIT, NULL); break; case EVENT_CMD_COMMAND_DEINIT: input_driver_ctl(RARCH_INPUT_CTL_COMMAND_DEINIT, NULL); break; case EVENT_CMD_COMMAND_INIT: event_cmd_ctl(EVENT_CMD_COMMAND_DEINIT, NULL); input_driver_ctl(RARCH_INPUT_CTL_COMMAND_INIT, NULL); break; case EVENT_CMD_REMOTE_DEINIT: input_driver_ctl(RARCH_INPUT_CTL_REMOTE_DEINIT, NULL); break; case EVENT_CMD_REMOTE_INIT: event_cmd_ctl(EVENT_CMD_REMOTE_DEINIT, NULL); input_driver_ctl(RARCH_INPUT_CTL_REMOTE_INIT, NULL); break; case EVENT_CMD_TEMPORARY_CONTENT_DEINIT: content_ctl(CONTENT_CTL_DEINIT, NULL); break; case EVENT_CMD_SUBSYSTEM_FULLPATHS_DEINIT: { global_t *global = global_get_ptr(); if (!global) break; if (global->subsystem_fullpaths) string_list_free(global->subsystem_fullpaths); global->subsystem_fullpaths = NULL; } break; case EVENT_CMD_LOG_FILE_DEINIT: retro_main_log_file_deinit(); break; case EVENT_CMD_DISK_APPEND_IMAGE: { const char *path = (const char*)data; if (string_is_empty(path)) return false; return event_disk_control_append_image(path); } case EVENT_CMD_DISK_EJECT_TOGGLE: if (info && info->disk_control_cb.get_num_images) { const struct retro_disk_control_callback *control = (const struct retro_disk_control_callback*) &info->disk_control_cb; if (control) { bool new_state = !control->get_eject_state(); event_disk_control_set_eject(new_state, true); } } else runloop_msg_queue_push( msg_hash_to_str(MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS), 1, 120, true); break; case EVENT_CMD_DISK_NEXT: if (info && info->disk_control_cb.get_num_images) { const struct retro_disk_control_callback *control = (const struct retro_disk_control_callback*) &info->disk_control_cb; if (!control) return false; if (!control->get_eject_state()) return false; event_check_disk_next(control); } else runloop_msg_queue_push( msg_hash_to_str(MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS), 1, 120, true); break; case EVENT_CMD_DISK_PREV: if (info && info->disk_control_cb.get_num_images) { const struct retro_disk_control_callback *control = (const struct retro_disk_control_callback*) &info->disk_control_cb; if (!control) return false; if (!control->get_eject_state()) return false; event_check_disk_prev(control); } else runloop_msg_queue_push( msg_hash_to_str(MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS), 1, 120, true); break; case EVENT_CMD_RUMBLE_STOP: for (i = 0; i < MAX_USERS; i++) { input_driver_set_rumble_state(i, RETRO_RUMBLE_STRONG, 0); input_driver_set_rumble_state(i, RETRO_RUMBLE_WEAK, 0); } break; case EVENT_CMD_GRAB_MOUSE_TOGGLE: { bool ret = false; static bool grab_mouse_state = false; grab_mouse_state = !grab_mouse_state; if (grab_mouse_state) ret = input_driver_ctl(RARCH_INPUT_CTL_GRAB_MOUSE, NULL); else ret = input_driver_ctl(RARCH_INPUT_CTL_UNGRAB_MOUSE, NULL); if (!ret) return false; RARCH_LOG("%s: %s.\n", msg_hash_to_str(MSG_GRAB_MOUSE_STATE), grab_mouse_state ? "yes" : "no"); if (grab_mouse_state) video_driver_ctl(RARCH_DISPLAY_CTL_HIDE_MOUSE, NULL); else video_driver_ctl(RARCH_DISPLAY_CTL_SHOW_MOUSE, NULL); } break; case EVENT_CMD_PERFCNT_REPORT_FRONTEND_LOG: rarch_perf_log(); break; case EVENT_CMD_VOLUME_UP: event_set_volume(0.5f); break; case EVENT_CMD_VOLUME_DOWN: event_set_volume(-0.5f); break; case EVENT_CMD_SET_FRAME_LIMIT: runloop_ctl(RUNLOOP_CTL_SET_FRAME_LIMIT, NULL); break; case EVENT_CMD_EXEC: return event_cmd_exec(data); case EVENT_CMD_NONE: default: return false; } return true; }
void recording_dump_frame(const void *data, unsigned width, unsigned height, size_t pitch) { struct ffemu_video_data ffemu_data = {0}; driver_t *driver = driver_get_ptr(); global_t *global = global_get_ptr(); if (!driver->recording_data) return; ffemu_data.pitch = pitch; ffemu_data.width = width; ffemu_data.height = height; ffemu_data.data = data; if (global->record.gpu_buffer) { struct video_viewport vp = {0}; video_driver_viewport_info(&vp); if (!vp.width || !vp.height) { RARCH_WARN("%s \n", msg_hash_to_str(MSG_VIEWPORT_SIZE_CALCULATION_FAILED)); event_command(EVENT_CMD_GPU_RECORD_DEINIT); recording_dump_frame(data, width, height, pitch); return; } /* User has resized. We kinda have a problem now. */ if (vp.width != global->record.gpu_width || vp.height != global->record.gpu_height) { RARCH_WARN("%s\n", msg_hash_to_str(MSG_RECORDING_TERMINATED_DUE_TO_RESIZE)); rarch_main_msg_queue_push_new(MSG_RECORDING_TERMINATED_DUE_TO_RESIZE, 1, 180, true); event_command(EVENT_CMD_RECORD_DEINIT); return; } /* Big bottleneck. * Since we might need to do read-backs asynchronously, * it might take 3-4 times before this returns true. */ if (!video_driver_read_viewport(global->record.gpu_buffer)) return; ffemu_data.pitch = global->record.gpu_width * 3; ffemu_data.width = global->record.gpu_width; ffemu_data.height = global->record.gpu_height; ffemu_data.data = global->record.gpu_buffer + (ffemu_data.height - 1) * ffemu_data.pitch; ffemu_data.pitch = -ffemu_data.pitch; } if (!global->record.gpu_buffer) ffemu_data.is_dupe = !data; if (driver->recording && driver->recording->push_video) driver->recording->push_video(driver->recording_data, &ffemu_data); }
/** * event_command: * @cmd : Event command index. * * Performs program event command with index @cmd. * * Returns: true (1) on success, otherwise false (0). **/ bool event_command(enum event_command cmd) { unsigned i = 0; bool boolean = false; driver_t *driver = driver_get_ptr(); global_t *global = global_get_ptr(); settings_t *settings = config_get_ptr(); rarch_system_info_t *system = rarch_system_info_get_ptr(); (void)i; switch (cmd) { case EVENT_CMD_LOAD_CONTENT_PERSIST: #ifdef HAVE_DYNAMIC event_command(EVENT_CMD_LOAD_CORE); #endif rarch_main_set_state(RARCH_ACTION_STATE_LOAD_CONTENT); break; #ifdef HAVE_FFMPEG case EVENT_CMD_LOAD_CONTENT_FFMPEG: rarch_main_set_state(RARCH_ACTION_STATE_LOAD_CONTENT_FFMPEG); break; #endif case EVENT_CMD_LOAD_CONTENT_IMAGEVIEWER: rarch_main_set_state(RARCH_ACTION_STATE_LOAD_CONTENT_IMAGEVIEWER); break; case EVENT_CMD_LOAD_CONTENT: #ifdef HAVE_DYNAMIC event_command(EVENT_CMD_LOAD_CONTENT_PERSIST); #else rarch_environment_cb(RETRO_ENVIRONMENT_SET_LIBRETRO_PATH, (void*)settings->libretro); rarch_environment_cb(RETRO_ENVIRONMENT_EXEC, (void*)global->path.fullpath); event_command(EVENT_CMD_QUIT); #endif break; case EVENT_CMD_LOAD_CORE_DEINIT: #ifdef HAVE_DYNAMIC libretro_free_system_info(&global->menu.info); #endif break; case EVENT_CMD_LOAD_CORE_PERSIST: event_command(EVENT_CMD_LOAD_CORE_DEINIT); { #ifdef HAVE_MENU menu_handle_t *menu = menu_driver_get_ptr(); if (menu) event_update_system_info(&global->menu.info, &menu->load_no_content); #endif } break; case EVENT_CMD_LOAD_CORE: event_command(EVENT_CMD_LOAD_CORE_PERSIST); #ifndef HAVE_DYNAMIC event_command(EVENT_CMD_QUIT); #endif break; case EVENT_CMD_LOAD_STATE: /* Immutable - disallow savestate load when * we absolutely cannot change game state. */ if (global->bsv.movie) return false; #ifdef HAVE_NETPLAY if (driver->netplay_data) return false; #endif event_main_state(cmd); break; case EVENT_CMD_RESIZE_WINDOWED_SCALE: if (global->pending.windowed_scale == 0) return false; settings->video.scale = global->pending.windowed_scale; if (!settings->video.fullscreen) event_command(EVENT_CMD_REINIT); global->pending.windowed_scale = 0; break; case EVENT_CMD_MENU_TOGGLE: if (menu_driver_alive()) rarch_main_set_state(RARCH_ACTION_STATE_MENU_RUNNING_FINISHED); else rarch_main_set_state(RARCH_ACTION_STATE_MENU_RUNNING); break; case EVENT_CMD_CONTROLLERS_INIT: event_init_controllers(); break; case EVENT_CMD_RESET: RARCH_LOG("%s.\n", msg_hash_to_str(MSG_RESET)); rarch_main_msg_queue_push_new(MSG_RESET, 1, 120, true); pretro_reset(); /* bSNES since v073r01 resets controllers to JOYPAD * after a reset, so just enforce it here. */ event_command(EVENT_CMD_CONTROLLERS_INIT); break; case EVENT_CMD_SAVE_STATE: if (settings->savestate_auto_index) settings->state_slot++; event_main_state(cmd); break; case EVENT_CMD_TAKE_SCREENSHOT: if (!take_screenshot()) return false; break; case EVENT_CMD_PREPARE_DUMMY: { #ifdef HAVE_MENU menu_handle_t *menu = menu_driver_get_ptr(); if (menu) menu->load_no_content = false; #endif rarch_main_data_deinit(); *global->path.fullpath = '\0'; rarch_main_set_state(RARCH_ACTION_STATE_LOAD_CONTENT); } break; case EVENT_CMD_UNLOAD_CORE: event_command(EVENT_CMD_PREPARE_DUMMY); event_command(EVENT_CMD_LOAD_CORE_DEINIT); break; case EVENT_CMD_QUIT: rarch_main_set_state(RARCH_ACTION_STATE_QUIT); break; case EVENT_CMD_REINIT: { const struct retro_hw_render_callback *hw_render = (const struct retro_hw_render_callback*)video_driver_callback(); const input_driver_t *input = driver ? (const input_driver_t*)driver->input : NULL; driver->video_cache_context = hw_render->cache_context; driver->video_cache_context_ack = false; event_command(EVENT_CMD_RESET_CONTEXT); driver->video_cache_context = false; /* Poll input to avoid possibly stale data to corrupt things. */ input->poll(driver->input_data); #ifdef HAVE_MENU menu_display_fb_set_dirty(); if (menu_driver_alive()) event_command(EVENT_CMD_VIDEO_SET_BLOCKING_STATE); #endif } break; case EVENT_CMD_CHEATS_DEINIT: if (!global) break; if (global->cheat) cheat_manager_free(global->cheat); global->cheat = NULL; break; case EVENT_CMD_CHEATS_INIT: event_command(EVENT_CMD_CHEATS_DEINIT); event_init_cheats(); break; case EVENT_CMD_REMAPPING_DEINIT: break; case EVENT_CMD_REMAPPING_INIT: event_command(EVENT_CMD_REMAPPING_DEINIT); event_init_remapping(); break; case EVENT_CMD_REWIND_DEINIT: if (!global) break; #ifdef HAVE_NETPLAY if (driver->netplay_data) return false; #endif if (global->rewind.state) state_manager_free(global->rewind.state); global->rewind.state = NULL; break; case EVENT_CMD_REWIND_INIT: init_rewind(); break; case EVENT_CMD_REWIND_TOGGLE: if (settings->rewind_enable) event_command(EVENT_CMD_REWIND_INIT); else event_command(EVENT_CMD_REWIND_DEINIT); break; case EVENT_CMD_AUTOSAVE_DEINIT: #ifdef HAVE_THREADS event_deinit_autosave(); #endif break; case EVENT_CMD_AUTOSAVE_INIT: event_command(EVENT_CMD_AUTOSAVE_DEINIT); #ifdef HAVE_THREADS event_init_autosave(); #endif break; case EVENT_CMD_AUTOSAVE_STATE: event_save_auto_state(); break; case EVENT_CMD_AUDIO_STOP: if (!driver->audio_data) return false; if (!audio_driver_alive()) return false; if (!audio_driver_stop()) return false; break; case EVENT_CMD_AUDIO_START: if (!driver->audio_data || audio_driver_alive()) return false; if (!settings->audio.mute_enable && !audio_driver_start()) { RARCH_ERR("Failed to start audio driver. Will continue without audio.\n"); driver->audio_active = false; } break; case EVENT_CMD_AUDIO_MUTE_TOGGLE: { const char *msg = !settings->audio.mute_enable ? msg_hash_to_str(MSG_AUDIO_MUTED): msg_hash_to_str(MSG_AUDIO_UNMUTED); if (!audio_driver_mute_toggle()) { RARCH_ERR("%s.\n", msg_hash_to_str(MSG_FAILED_TO_UNMUTE_AUDIO)); return false; } rarch_main_msg_queue_push(msg, 1, 180, true); RARCH_LOG("%s\n", msg); } break; case EVENT_CMD_OVERLAY_DEINIT: #ifdef HAVE_OVERLAY input_overlay_free_ptr(); #endif break; case EVENT_CMD_OVERLAY_INIT: event_command(EVENT_CMD_OVERLAY_DEINIT); #ifdef HAVE_OVERLAY if (input_overlay_new_ptr() == -1) RARCH_ERR("%s.\n", msg_hash_to_str(MSG_FAILED_TO_LOAD_OVERLAY)); #endif break; case EVENT_CMD_OVERLAY_NEXT: #ifdef HAVE_OVERLAY input_overlay_next(settings->input.overlay_opacity); #endif break; case EVENT_CMD_DSP_FILTER_DEINIT: if (!global) break; audio_driver_dsp_filter_free(); break; case EVENT_CMD_DSP_FILTER_INIT: event_command(EVENT_CMD_DSP_FILTER_DEINIT); if (!*settings->audio.dsp_plugin) break; audio_driver_dsp_filter_init(settings->audio.dsp_plugin); break; case EVENT_CMD_GPU_RECORD_DEINIT: if (!global) break; if (global->record.gpu_buffer) free(global->record.gpu_buffer); global->record.gpu_buffer = NULL; break; case EVENT_CMD_RECORD_DEINIT: if (!recording_deinit()) return false; break; case EVENT_CMD_RECORD_INIT: event_command(EVENT_CMD_HISTORY_DEINIT); if (!recording_init()) return false; break; case EVENT_CMD_HISTORY_DEINIT: if (g_defaults.history) { content_playlist_write_file(g_defaults.history); content_playlist_free(g_defaults.history); } g_defaults.history = NULL; break; case EVENT_CMD_HISTORY_INIT: event_command(EVENT_CMD_HISTORY_DEINIT); if (!settings->history_list_enable) return false; RARCH_LOG("%s: [%s].\n", msg_hash_to_str(MSG_LOADING_HISTORY_FILE), settings->content_history_path); g_defaults.history = content_playlist_init( settings->content_history_path, settings->content_history_size); break; case EVENT_CMD_CORE_INFO_DEINIT: if (!global) break; if (global->core_info.list) core_info_list_free(global->core_info.list); global->core_info.list = NULL; break; case EVENT_CMD_DATA_RUNLOOP_FREE: rarch_main_data_free(); break; case EVENT_CMD_CORE_INFO_INIT: event_command(EVENT_CMD_CORE_INFO_DEINIT); if (*settings->libretro_directory) global->core_info.list = core_info_list_new(); break; case EVENT_CMD_CORE_DEINIT: { struct retro_hw_render_callback *cb = video_driver_callback(); event_deinit_core(true); if (cb) memset(cb, 0, sizeof(*cb)); break; } case EVENT_CMD_CORE_INIT: if (!event_init_core()) return false; break; case EVENT_CMD_VIDEO_APPLY_STATE_CHANGES: video_driver_apply_state_changes(); break; case EVENT_CMD_VIDEO_SET_NONBLOCKING_STATE: boolean = true; /* fall-through */ case EVENT_CMD_VIDEO_SET_BLOCKING_STATE: video_driver_set_nonblock_state(boolean); break; case EVENT_CMD_VIDEO_SET_ASPECT_RATIO: video_driver_set_aspect_ratio(settings->video.aspect_ratio_idx); break; case EVENT_CMD_AUDIO_SET_NONBLOCKING_STATE: boolean = true; /* fall-through */ case EVENT_CMD_AUDIO_SET_BLOCKING_STATE: audio_driver_set_nonblock_state(boolean); break; case EVENT_CMD_OVERLAY_SET_SCALE_FACTOR: #ifdef HAVE_OVERLAY input_overlay_set_scale_factor(settings->input.overlay_scale); #endif break; case EVENT_CMD_OVERLAY_SET_ALPHA_MOD: #ifdef HAVE_OVERLAY input_overlay_set_alpha_mod(settings->input.overlay_opacity); #endif break; case EVENT_CMD_DRIVERS_DEINIT: uninit_drivers(DRIVERS_CMD_ALL); break; case EVENT_CMD_DRIVERS_INIT: init_drivers(DRIVERS_CMD_ALL); break; case EVENT_CMD_AUDIO_REINIT: uninit_drivers(DRIVER_AUDIO); init_drivers(DRIVER_AUDIO); break; case EVENT_CMD_RESET_CONTEXT: event_command(EVENT_CMD_DRIVERS_DEINIT); event_command(EVENT_CMD_DRIVERS_INIT); break; case EVENT_CMD_QUIT_RETROARCH: rarch_main_set_state(RARCH_ACTION_STATE_FORCE_QUIT); break; case EVENT_CMD_RESUME: rarch_main_set_state(RARCH_ACTION_STATE_MENU_RUNNING_FINISHED); break; case EVENT_CMD_RESTART_RETROARCH: #if defined(GEKKO) && defined(HW_RVL) fill_pathname_join(global->path.fullpath, g_defaults.dir.core, SALAMANDER_FILE, sizeof(global->path.fullpath)); #endif if (driver->frontend_ctx && driver->frontend_ctx->set_fork) driver->frontend_ctx->set_fork(true, false); break; case EVENT_CMD_MENU_SAVE_CONFIG: if (!event_save_core_config()) return false; break; case EVENT_CMD_SHADERS_APPLY_CHANGES: #ifdef HAVE_MENU menu_shader_manager_apply_changes(); #endif break; case EVENT_CMD_PAUSE_CHECKS: if (rarch_main_is_paused()) { RARCH_LOG("%s\n", msg_hash_to_str(MSG_PAUSED)); event_command(EVENT_CMD_AUDIO_STOP); if (settings->video.black_frame_insertion) video_driver_cached_frame(); } else { RARCH_LOG("%s\n", msg_hash_to_str(MSG_UNPAUSED)); event_command(EVENT_CMD_AUDIO_START); } break; case EVENT_CMD_PAUSE_TOGGLE: rarch_main_set_pause(!rarch_main_is_paused()); event_command(EVENT_CMD_PAUSE_CHECKS); break; case EVENT_CMD_UNPAUSE: rarch_main_set_pause(false); event_command(EVENT_CMD_PAUSE_CHECKS); break; case EVENT_CMD_PAUSE: rarch_main_set_pause(true); event_command(EVENT_CMD_PAUSE_CHECKS); break; case EVENT_CMD_MENU_PAUSE_LIBRETRO: if (menu_driver_alive()) { if (settings->menu.pause_libretro) event_command(EVENT_CMD_AUDIO_STOP); else event_command(EVENT_CMD_AUDIO_START); } else { if (settings->menu.pause_libretro) event_command(EVENT_CMD_AUDIO_START); } break; case EVENT_CMD_SHADER_DIR_DEINIT: if (!global) break; dir_list_free(global->shader_dir.list); global->shader_dir.list = NULL; global->shader_dir.ptr = 0; break; case EVENT_CMD_SHADER_DIR_INIT: event_command(EVENT_CMD_SHADER_DIR_DEINIT); if (!*settings->video.shader_dir) return false; global->shader_dir.list = dir_list_new_special(NULL, DIR_LIST_SHADERS); if (!global->shader_dir.list || global->shader_dir.list->size == 0) { event_command(EVENT_CMD_SHADER_DIR_DEINIT); return false; } global->shader_dir.ptr = 0; dir_list_sort(global->shader_dir.list, false); for (i = 0; i < global->shader_dir.list->size; i++) RARCH_LOG("%s \"%s\"\n", msg_hash_to_str(MSG_FOUND_SHADER), global->shader_dir.list->elems[i].data); break; case EVENT_CMD_SAVEFILES: event_save_files(); break; case EVENT_CMD_SAVEFILES_DEINIT: if (!global) break; if (global->savefiles) string_list_free(global->savefiles); global->savefiles = NULL; break; case EVENT_CMD_SAVEFILES_INIT: global->sram.use = global->sram.use && !global->sram.save_disable #ifdef HAVE_NETPLAY && (!driver->netplay_data || !global->netplay.is_client) #endif ; if (!global->sram.use) RARCH_LOG("%s\n", msg_hash_to_str(MSG_SRAM_WILL_NOT_BE_SAVED)); if (global->sram.use) event_command(EVENT_CMD_AUTOSAVE_INIT); break; case EVENT_CMD_MSG_QUEUE_DEINIT: rarch_main_msg_queue_free(); break; case EVENT_CMD_MSG_QUEUE_INIT: event_command(EVENT_CMD_MSG_QUEUE_DEINIT); rarch_main_msg_queue_init(); rarch_main_data_init_queues(); break; case EVENT_CMD_BSV_MOVIE_DEINIT: if (!global) break; if (global->bsv.movie) bsv_movie_free(global->bsv.movie); global->bsv.movie = NULL; break; case EVENT_CMD_BSV_MOVIE_INIT: event_command(EVENT_CMD_BSV_MOVIE_DEINIT); event_init_movie(); break; case EVENT_CMD_NETPLAY_DEINIT: #ifdef HAVE_NETPLAY deinit_netplay(); #endif break; case EVENT_CMD_NETWORK_DEINIT: #ifdef HAVE_NETWORKING network_deinit(); #endif break; case EVENT_CMD_NETWORK_INIT: #ifdef HAVE_NETWORKING network_init(); #endif break; case EVENT_CMD_NETPLAY_INIT: event_command(EVENT_CMD_NETPLAY_DEINIT); #ifdef HAVE_NETPLAY if (!init_netplay()) return false; #endif break; case EVENT_CMD_NETPLAY_FLIP_PLAYERS: #ifdef HAVE_NETPLAY { netplay_t *netplay = (netplay_t*)driver->netplay_data; if (!netplay) return false; netplay_flip_users(netplay); } #endif break; case EVENT_CMD_FULLSCREEN_TOGGLE: if (!video_driver_has_windowed()) return false; /* If we go fullscreen we drop all drivers and * reinitialize to be safe. */ settings->video.fullscreen = !settings->video.fullscreen; event_command(EVENT_CMD_REINIT); break; case EVENT_CMD_COMMAND_DEINIT: #ifdef HAVE_COMMAND if (driver->command) rarch_cmd_free(driver->command); driver->command = NULL; #endif break; case EVENT_CMD_COMMAND_INIT: event_command(EVENT_CMD_COMMAND_DEINIT); #ifdef HAVE_COMMAND event_init_command(); #endif break; case EVENT_CMD_TEMPORARY_CONTENT_DEINIT: if (!global) break; if (global->temporary_content) event_free_temporary_content(); global->temporary_content = NULL; break; case EVENT_CMD_SUBSYSTEM_FULLPATHS_DEINIT: if (!global) break; if (global->subsystem_fullpaths) string_list_free(global->subsystem_fullpaths); global->subsystem_fullpaths = NULL; break; case EVENT_CMD_LOG_FILE_DEINIT: if (!global) break; if (global->log_file && global->log_file != stderr) fclose(global->log_file); global->log_file = NULL; break; case EVENT_CMD_DISK_EJECT_TOGGLE: if (system && system->disk_control.get_num_images) { const struct retro_disk_control_callback *control = (const struct retro_disk_control_callback*) &system->disk_control; if (control) event_check_disk_eject(control); } else rarch_main_msg_queue_push_new( MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS, 1, 120, true); break; case EVENT_CMD_DISK_NEXT: if (system && system->disk_control.get_num_images) { const struct retro_disk_control_callback *control = (const struct retro_disk_control_callback*) &system->disk_control; if (!control) return false; if (!control->get_eject_state()) return false; event_check_disk_next(control); } else rarch_main_msg_queue_push_new( MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS, 1, 120, true); break; case EVENT_CMD_DISK_PREV: if (system && system->disk_control.get_num_images) { const struct retro_disk_control_callback *control = (const struct retro_disk_control_callback*) &system->disk_control; if (!control) return false; if (!control->get_eject_state()) return false; event_check_disk_prev(control); } else rarch_main_msg_queue_push_new( MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS, 1, 120, true); break; case EVENT_CMD_RUMBLE_STOP: for (i = 0; i < MAX_USERS; i++) { input_driver_set_rumble_state(i, RETRO_RUMBLE_STRONG, 0); input_driver_set_rumble_state(i, RETRO_RUMBLE_WEAK, 0); } break; case EVENT_CMD_GRAB_MOUSE_TOGGLE: { static bool grab_mouse_state = false; grab_mouse_state = !grab_mouse_state; if (!driver->input || !input_driver_grab_mouse(grab_mouse_state)) return false; RARCH_LOG("%s: %s.\n", msg_hash_to_str(MSG_GRAB_MOUSE_STATE), grab_mouse_state ? "yes" : "no"); video_driver_show_mouse(!grab_mouse_state); } break; case EVENT_CMD_PERFCNT_REPORT_FRONTEND_LOG: rarch_perf_log(); break; case EVENT_CMD_VOLUME_UP: event_set_volume(0.5f); break; case EVENT_CMD_VOLUME_DOWN: event_set_volume(-0.5f); break; case EVENT_CMD_NONE: default: return false; } return true; }
/** * menu_init: * @data : Menu context handle. * * Create and initialize menu handle. * * Returns: menu handle on success, otherwise NULL. **/ void *menu_init(const void *data) { menu_handle_t *menu = NULL; menu_display_t *disp = NULL; menu_ctx_driver_t *menu_ctx = (menu_ctx_driver_t*)data; global_t *global = global_get_ptr(); settings_t *settings = config_get_ptr(); if (!menu_ctx) return NULL; if (!(menu = (menu_handle_t*)menu_ctx->init())) return NULL; strlcpy(settings->menu.driver, menu_ctx->ident, sizeof(settings->menu.driver)); if (!menu_entries_init(menu)) goto error; global->core_info.current = (core_info_t*)calloc(1, sizeof(core_info_t)); if (!global->core_info.current) goto error; #ifdef HAVE_SHADER_MANAGER menu->shader = (struct video_shader*)calloc(1, sizeof(struct video_shader)); if (!menu->shader) goto error; #endif menu->push_help_screen = settings->menu_show_start_screen; menu->help_screen_type = MENU_HELP_WELCOME; settings->menu_show_start_screen = false; #if 0 if (settings->bundle_assets_extract_enable && (strcmp(PACKAGE_VERSION, settings->bundle_assets_last_extracted_version) != 0) ) { menu->push_help_screen = true; menu->help_screen_type = MENU_HELP_EXTRACT; rarch_main_data_msg_queue_push(DATA_TYPE_FILE, "cb_bundle_extract", "cb_bundle_extract", 0, 1, true); } #endif menu_shader_manager_init(menu); if (!menu_display_init(menu)) goto error; disp = &menu->display; rarch_assert(disp->msg_queue = msg_queue_new(8)); return menu; error: menu_free(menu); return NULL; }
/** * event_save_core_config: * * Saves a new (core) configuration to a file. Filename is based * on heuristics to avoid typing. * * Returns: true (1) on success, otherwise false (0). **/ static bool event_save_core_config(void) { char config_dir[PATH_MAX_LENGTH] = {0}; char config_name[PATH_MAX_LENGTH] = {0}; char config_path[PATH_MAX_LENGTH] = {0}; char msg[PATH_MAX_LENGTH] = {0}; bool ret = false; bool found_path = false; bool overrides_active = false; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); *config_dir = '\0'; if (*settings->menu_config_directory) strlcpy(config_dir, settings->menu_config_directory, sizeof(config_dir)); else if (*global->path.config) /* Fallback */ fill_pathname_basedir(config_dir, global->path.config, sizeof(config_dir)); else { rarch_main_msg_queue_push_new(MSG_CONFIG_DIRECTORY_NOT_SET, 1, 180, true); RARCH_ERR("%s\n", msg_hash_to_str(MSG_CONFIG_DIRECTORY_NOT_SET)); return false; } /* Infer file name based on libretro core. */ if (*settings->libretro && path_file_exists(settings->libretro)) { unsigned i; /* In case of collision, find an alternative name. */ for (i = 0; i < 16; i++) { char tmp[64] = {0}; fill_pathname_base(config_name, settings->libretro, sizeof(config_name)); path_remove_extension(config_name); fill_pathname_join(config_path, config_dir, config_name, sizeof(config_path)); *tmp = '\0'; if (i) snprintf(tmp, sizeof(tmp), "-%u.cfg", i); else strlcpy(tmp, ".cfg", sizeof(tmp)); strlcat(config_path, tmp, sizeof(config_path)); if (!path_file_exists(config_path)) { found_path = true; break; } } } /* Fallback to system time... */ if (!found_path) { RARCH_WARN("Cannot infer new config path. Use current time.\n"); fill_dated_filename(config_name, "cfg", sizeof(config_name)); fill_pathname_join(config_path, config_dir, config_name, sizeof(config_path)); } /* Overrides block config file saving, make it appear as overrides weren't enabled for a manual save */ if (global->overrides_active) { global->overrides_active = false; overrides_active = true; } if ((ret = config_save_file(config_path))) { strlcpy(global->path.config, config_path, sizeof(global->path.config)); snprintf(msg, sizeof(msg), "Saved new config to \"%s\".", config_path); RARCH_LOG("%s\n", msg); } else { snprintf(msg, sizeof(msg), "Failed saving config to \"%s\".", config_path); RARCH_ERR("%s\n", msg); } rarch_main_msg_queue_push(msg, 1, 180, true); global->overrides_active = overrides_active; return ret; }
static bool gfx_ctx_glx_init(void *data) { static const int visual_attribs[] = { GLX_X_RENDERABLE , True, GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, GLX_RENDER_TYPE , GLX_RGBA_BIT, GLX_DOUBLEBUFFER , True, GLX_RED_SIZE , 8, GLX_GREEN_SIZE , 8, GLX_BLUE_SIZE , 8, GLX_ALPHA_SIZE , 8, GLX_DEPTH_SIZE , 0, GLX_STENCIL_SIZE , 0, None }; int nelements, major, minor; GLXFBConfig *fbcs = NULL; gfx_ctx_glx_data_t *glx = (gfx_ctx_glx_data_t*)calloc(1, sizeof(gfx_ctx_glx_data_t)); driver_t *driver = driver_get_ptr(); global_t *global = global_get_ptr(); if (!glx) return false; XInitThreads(); g_quit = 0; if (!glx->g_dpy) glx->g_dpy = XOpenDisplay(NULL); if (!glx->g_dpy) goto error; glXQueryVersion(glx->g_dpy, &major, &minor); /* GLX 1.3+ minimum required. */ if ((major * 1000 + minor) < 1003) goto error; glx_create_context_attribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); #ifdef GL_DEBUG glx->g_debug = true; #else glx->g_debug = global->system.hw_render_callback.debug_context; #endif /* Have to use ContextAttribs */ #ifdef HAVE_OPENGLES2 glx->g_core_es = true; glx->g_core_es_core = true; #else glx->g_core_es = (g_major * 1000 + g_minor) >= 3001; glx->g_core_es_core = (g_major * 1000 + g_minor) >= 3002; #endif if ((glx->g_core_es || glx->g_debug) && !glx_create_context_attribs) goto error; fbcs = glXChooseFBConfig(glx->g_dpy, DefaultScreen(glx->g_dpy), visual_attribs, &nelements); if (!fbcs) goto error; if (!nelements) { XFree(fbcs); goto error; } glx->g_fbc = fbcs[0]; XFree(fbcs); driver->video_context_data = glx; return true; error: ctx_glx_destroy_resources(glx); if (glx) free(glx); return false; }
void recording_dump_frame(const void *data, unsigned width, unsigned height, size_t pitch) { struct ffemu_video_data ffemu_data = {0}; global_t *global = global_get_ptr(); if (!recording_data) return; ffemu_data.pitch = pitch; ffemu_data.width = width; ffemu_data.height = height; ffemu_data.data = data; if (video_driver_ctl(RARCH_DISPLAY_CTL_HAS_GPU_RECORD, NULL)) { uint8_t *gpu_buf = NULL; struct video_viewport vp = {0}; video_driver_viewport_info(&vp); if (!vp.width || !vp.height) { RARCH_WARN("%s \n", msg_hash_to_str(MSG_VIEWPORT_SIZE_CALCULATION_FAILED)); event_cmd_ctl(EVENT_CMD_GPU_RECORD_DEINIT, NULL); recording_dump_frame(data, width, height, pitch); return; } /* User has resized. We kinda have a problem now. */ if (vp.width != global->record.gpu_width || vp.height != global->record.gpu_height) { RARCH_WARN("%s\n", msg_hash_to_str(MSG_RECORDING_TERMINATED_DUE_TO_RESIZE)); runloop_msg_queue_push_new(MSG_RECORDING_TERMINATED_DUE_TO_RESIZE, 1, 180, true); event_cmd_ctl(EVENT_CMD_RECORD_DEINIT, NULL); return; } if (!video_driver_ctl(RARCH_DISPLAY_CTL_GPU_RECORD_GET, &gpu_buf)) return; /* Big bottleneck. * Since we might need to do read-backs asynchronously, * it might take 3-4 times before this returns true. */ if (!video_driver_ctl(RARCH_DISPLAY_CTL_READ_VIEWPORT, gpu_buf)) return; ffemu_data.pitch = global->record.gpu_width * 3; ffemu_data.width = global->record.gpu_width; ffemu_data.height = global->record.gpu_height; ffemu_data.data = gpu_buf + (ffemu_data.height - 1) * ffemu_data.pitch; ffemu_data.pitch = -ffemu_data.pitch; } if (!video_driver_ctl(RARCH_DISPLAY_CTL_HAS_GPU_RECORD, NULL)) ffemu_data.is_dupe = !data; if (recording_driver && recording_driver->push_video) recording_driver->push_video(recording_data, &ffemu_data); }
static void *gfx_ctx_ps3_init(void *video_driver) { #ifdef HAVE_PSGL PSGLdeviceParameters params; PSGLinitOptions options; #endif global_t *global = global_get_ptr(); gfx_ctx_ps3_data_t *ps3 = (gfx_ctx_ps3_data_t*) calloc(1, sizeof(gfx_ctx_ps3_data_t)); (void)video_driver; (void)global; if (!ps3) return NULL; #if defined(HAVE_PSGL) options.enable = PSGL_INIT_MAX_SPUS | PSGL_INIT_INITIALIZE_SPUS; options.maxSPUs = 1; options.initializeSPUs = GL_FALSE; /* Initialize 6 SPUs but reserve 1 SPU as a raw SPU for PSGL. */ sys_spu_initialize(6, 1); psglInit(&options); params.enable = PSGL_DEVICE_PARAMETERS_COLOR_FORMAT | PSGL_DEVICE_PARAMETERS_DEPTH_FORMAT | PSGL_DEVICE_PARAMETERS_MULTISAMPLING_MODE; params.colorFormat = GL_ARGB_SCE; params.depthFormat = GL_NONE; params.multisamplingMode = GL_MULTISAMPLING_NONE_SCE; if (global->console.screen.resolutions.current.id) { params.enable |= PSGL_DEVICE_PARAMETERS_WIDTH_HEIGHT; gfx_ctx_ps3_get_resolution( global->console.screen.resolutions.current.id, ¶ms.width, ¶ms.height); global->console.screen.pal_enable = false; if (params.width == 720 && params.height == 576) { RARCH_LOG("[PSGL Context]: 720x576 resolution detected, setting MODE_VIDEO_PAL_ENABLE.\n"); global->console.screen.pal_enable = true; } } if (global->console.screen.pal60_enable) { RARCH_LOG("[PSGL Context]: Setting temporal PAL60 mode.\n"); params.enable |= PSGL_DEVICE_PARAMETERS_RESC_PAL_TEMPORAL_MODE; params.enable |= PSGL_DEVICE_PARAMETERS_RESC_RATIO_MODE; params.rescPalTemporalMode = RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE; params.rescRatioMode = RESC_RATIO_MODE_FULLSCREEN; } ps3->gl_device = psglCreateDeviceExtended(¶ms); ps3->gl_context = psglCreateContext(); psglMakeCurrent(ps3->gl_context, ps3->gl_device); psglResetCurrentContext(); #endif global->console.screen.pal_enable = cellVideoOutGetResolutionAvailability( CELL_VIDEO_OUT_PRIMARY, CELL_VIDEO_OUT_RESOLUTION_576, CELL_VIDEO_OUT_ASPECT_AUTO, 0); gfx_ctx_ps3_get_available_resolutions(); return ps3; }
/** * rarch_environment_cb: * @cmd : Identifier of command. * @data : Pointer to data. * * Environment callback function implementation. * * Returns: true (1) if environment callback command could * be performed, otherwise false (0). **/ bool rarch_environment_cb(unsigned cmd, void *data) { unsigned p; driver_t *driver = driver_get_ptr(); settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); rarch_system_info_t *system = rarch_system_info_get_ptr(); char buf[PATH_MAX_LENGTH]; if (ignore_environment_cb) return false; switch (cmd) { case RETRO_ENVIRONMENT_GET_OVERSCAN: *(bool*)data = !settings->video.crop_overscan; RARCH_LOG("Environ GET_OVERSCAN: %u\n", (unsigned)!settings->video.crop_overscan); break; case RETRO_ENVIRONMENT_GET_CAN_DUPE: *(bool*)data = true; RARCH_LOG("Environ GET_CAN_DUPE: true\n"); break; case RETRO_ENVIRONMENT_GET_VARIABLE: { struct retro_variable *var = (struct retro_variable*)data; RARCH_LOG("Environ GET_VARIABLE %s:\n", var->key); if (system && system->core_options) core_option_get(system->core_options, var); else var->value = NULL; RARCH_LOG("\t%s\n", var->value ? var->value : "N/A"); break; } case RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE: *(bool*)data = system->core_options ? core_option_updated(system->core_options) : false; break; case RETRO_ENVIRONMENT_SET_VARIABLES: { RARCH_LOG("Environ SET_VARIABLES.\n"); if (system && system->core_options) { core_option_flush(system->core_options); core_option_free(system->core_options); } { const struct retro_variable *vars = (const struct retro_variable*)data; char buf[PATH_MAX_LENGTH] = {0}; const char *options_path = settings->core_options_path; if (!*options_path && *global->path.config) { fill_pathname_resolve_relative(buf, global->path.config, "retroarch-core-options.cfg", sizeof(buf)); options_path = buf; } system->core_options = core_option_new(options_path, vars); } break; } case RETRO_ENVIRONMENT_SET_MESSAGE: { const struct retro_message *msg = (const struct retro_message*)data; RARCH_LOG("Environ SET_MESSAGE: %s\n", msg->msg); rarch_main_msg_queue_push(msg->msg, 1, msg->frames, true); break; } case RETRO_ENVIRONMENT_SET_ROTATION: { unsigned rotation = *(const unsigned*)data; RARCH_LOG("Environ SET_ROTATION: %u\n", rotation); if (!settings->video.allow_rotate) break; system->rotation = rotation; if (!video_driver_set_rotation(rotation)) return false; break; } case RETRO_ENVIRONMENT_SHUTDOWN: RARCH_LOG("Environ SHUTDOWN.\n"); system->shutdown = true; global->core_shutdown_initiated = true; break; case RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL: system->performance_level = *(const unsigned*)data; RARCH_LOG("Environ PERFORMANCE_LEVEL: %u.\n", system->performance_level); break; case RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY: if (!settings->system_directory || settings->system_directory[0] == '\0') { RARCH_WARN("SYSTEM DIR is empty, assume CONTENT DIR %s\n",global->path.fullpath); fill_pathname_basedir(buf, global->path.fullpath, sizeof(buf)); } *(const char**)data = *settings->system_directory ? settings->system_directory : buf; RARCH_LOG("Environ SYSTEM_DIRECTORY: \"%s\".\n", settings->system_directory); break; case RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY: *(const char**)data = *global->dir.savefile ? global->dir.savefile : NULL; RARCH_LOG("Environ SAVE_DIRECTORY: \"%s\".\n", global->dir.savefile); break; case RETRO_ENVIRONMENT_GET_USERNAME: *(const char**)data = *settings->username ? settings->username : NULL; RARCH_LOG("Environ GET_USERNAME: \"%s\".\n", settings->username); break; case RETRO_ENVIRONMENT_GET_LANGUAGE: *(unsigned *)data = settings->user_language; RARCH_LOG("Environ GET_LANGUAGE: \"%u\".\n", settings->user_language); break; case RETRO_ENVIRONMENT_SET_PIXEL_FORMAT: { enum retro_pixel_format pix_fmt = *(const enum retro_pixel_format*)data; switch (pix_fmt) { case RETRO_PIXEL_FORMAT_0RGB1555: RARCH_LOG("Environ SET_PIXEL_FORMAT: 0RGB1555.\n"); break; case RETRO_PIXEL_FORMAT_RGB565: RARCH_LOG("Environ SET_PIXEL_FORMAT: RGB565.\n"); break; case RETRO_PIXEL_FORMAT_XRGB8888: RARCH_LOG("Environ SET_PIXEL_FORMAT: XRGB8888.\n"); break; default: return false; } video_driver_set_pixel_format(pix_fmt); break; } case RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS: { unsigned retro_id, retro_port; const struct retro_input_descriptor *desc = NULL; static const char *libretro_btn_desc[] = { "B (bottom)", "Y (left)", "Select", "Start", "D-Pad Up", "D-Pad Down", "D-Pad Left", "D-Pad Right", "A (right)", "X (up)", "L", "R", "L2", "R2", "L3", "R3", }; memset(system->input_desc_btn, 0, sizeof(system->input_desc_btn)); desc = (const struct retro_input_descriptor*)data; for (; desc->description; desc++) { retro_port = desc->port; retro_id = desc->id; if (desc->port >= MAX_USERS) continue; /* Ignore all others for now. */ if (desc->device != RETRO_DEVICE_JOYPAD && desc->device != RETRO_DEVICE_ANALOG) continue; if (desc->id >= RARCH_FIRST_CUSTOM_BIND) continue; if (desc->device == RETRO_DEVICE_ANALOG) { switch (retro_id) { case RETRO_DEVICE_ID_ANALOG_X: switch (desc->index) { case RETRO_DEVICE_INDEX_ANALOG_LEFT: system->input_desc_btn[retro_port][RARCH_ANALOG_LEFT_X_PLUS] = desc->description; system->input_desc_btn[retro_port][RARCH_ANALOG_LEFT_X_MINUS] = desc->description; break; case RETRO_DEVICE_INDEX_ANALOG_RIGHT: system->input_desc_btn[retro_port][RARCH_ANALOG_RIGHT_X_PLUS] = desc->description; system->input_desc_btn[retro_port][RARCH_ANALOG_RIGHT_X_MINUS] = desc->description; break; } break; case RETRO_DEVICE_ID_ANALOG_Y: switch (desc->index) { case RETRO_DEVICE_INDEX_ANALOG_LEFT: system->input_desc_btn[retro_port][RARCH_ANALOG_LEFT_Y_PLUS] = desc->description; system->input_desc_btn[retro_port][RARCH_ANALOG_LEFT_Y_MINUS] = desc->description; break; case RETRO_DEVICE_INDEX_ANALOG_RIGHT: system->input_desc_btn[retro_port][RARCH_ANALOG_RIGHT_Y_PLUS] = desc->description; system->input_desc_btn[retro_port][RARCH_ANALOG_RIGHT_Y_MINUS] = desc->description; break; } break; } } else system->input_desc_btn[retro_port][retro_id] = desc->description; } RARCH_LOG("Environ SET_INPUT_DESCRIPTORS:\n"); for (p = 0; p < settings->input.max_users; p++) { for (retro_id = 0; retro_id < RARCH_FIRST_CUSTOM_BIND; retro_id++) { const char *description = system->input_desc_btn[p][retro_id]; if (!description) continue; RARCH_LOG("\tRetroPad, User %u, Button \"%s\" => \"%s\"\n", p + 1, libretro_btn_desc[retro_id], description); } } global->has_set.input_descriptors = true; break; } case RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK: { const struct retro_keyboard_callback *info = (const struct retro_keyboard_callback*)data; RARCH_LOG("Environ SET_KEYBOARD_CALLBACK.\n"); system->key_event = info->callback; global->frontend_key_event = system->key_event; break; } case RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE: RARCH_LOG("Environ SET_DISK_CONTROL_INTERFACE.\n"); system->disk_control = *(const struct retro_disk_control_callback*)data; break; case RETRO_ENVIRONMENT_SET_HW_RENDER: case RETRO_ENVIRONMENT_SET_HW_RENDER | RETRO_ENVIRONMENT_EXPERIMENTAL: { struct retro_hw_render_callback *hw_render = video_driver_callback(); struct retro_hw_render_callback *cb = (struct retro_hw_render_callback*)data; RARCH_LOG("Environ SET_HW_RENDER.\n"); switch (cb->context_type) { case RETRO_HW_CONTEXT_NONE: RARCH_LOG("Requesting no HW context.\n"); break; #if defined(HAVE_OPENGLES2) case RETRO_HW_CONTEXT_OPENGLES2: #if defined(HAVE_OPENGLES3) case RETRO_HW_CONTEXT_OPENGLES3: #endif RARCH_LOG("Requesting OpenGLES%u context.\n", cb->context_type == RETRO_HW_CONTEXT_OPENGLES2 ? 2 : 3); break; #if defined(HAVE_OPENGLES3) case RETRO_HW_CONTEXT_OPENGLES_VERSION: RARCH_LOG("Requesting OpenGLES%u.%u context.\n", cb->version_major, cb->version_minor); break; #endif case RETRO_HW_CONTEXT_OPENGL: case RETRO_HW_CONTEXT_OPENGL_CORE: RARCH_ERR("Requesting OpenGL context, but RetroArch is compiled against OpenGLES2. Cannot use HW context.\n"); return false; #elif defined(HAVE_OPENGL) case RETRO_HW_CONTEXT_OPENGLES2: case RETRO_HW_CONTEXT_OPENGLES3: RARCH_ERR("Requesting OpenGLES%u context, but RetroArch is compiled against OpenGL. Cannot use HW context.\n", cb->context_type == RETRO_HW_CONTEXT_OPENGLES2 ? 2 : 3); return false; case RETRO_HW_CONTEXT_OPENGLES_VERSION: RARCH_ERR("Requesting OpenGLES%u.%u context, but RetroArch is compiled against OpenGL. Cannot use HW context.\n", cb->version_major, cb->version_minor); return false; case RETRO_HW_CONTEXT_OPENGL: RARCH_LOG("Requesting OpenGL context.\n"); break; case RETRO_HW_CONTEXT_OPENGL_CORE: RARCH_LOG("Requesting core OpenGL context (%u.%u).\n", cb->version_major, cb->version_minor); break; #endif default: RARCH_LOG("Requesting unknown context.\n"); return false; } cb->get_current_framebuffer = video_driver_get_current_framebuffer; cb->get_proc_address = video_driver_get_proc_address; if (cmd & RETRO_ENVIRONMENT_EXPERIMENTAL) /* Old ABI. Don't copy garbage. */ memcpy(hw_render, cb, offsetof(struct retro_hw_render_callback, stencil)); else memcpy(hw_render, cb, sizeof(*cb)); break; } case RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME: { bool state = *(const bool*)data; RARCH_LOG("Environ SET_SUPPORT_NO_GAME: %s.\n", state ? "yes" : "no"); system->no_content = state; break; } case RETRO_ENVIRONMENT_GET_LIBRETRO_PATH: { const char **path = (const char**)data; #ifdef HAVE_DYNAMIC *path = settings->libretro; #else *path = NULL; #endif break; } /* FIXME - PS3 audio driver needs to be fixed so that threaded * audio works correctly (audio is already on a thread for PS3 * audio driver so that's probably the problem) */ #if defined(HAVE_THREADS) && !defined(__CELLOS_LV2__) case RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK: { const struct retro_audio_callback *info = (const struct retro_audio_callback*)data; RARCH_LOG("Environ SET_AUDIO_CALLBACK.\n"); if (driver->recording_data) /* A/V sync is a must. */ return false; #ifdef HAVE_NETPLAY if (global->netplay.enable) return false; #endif audio_driver_set_callback(info); break; } #endif case RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK: { const struct retro_frame_time_callback *info = (const struct retro_frame_time_callback*)data; RARCH_LOG("Environ SET_FRAME_TIME_CALLBACK.\n"); #ifdef HAVE_NETPLAY /* retro_run() will be called in very strange and * mysterious ways, have to disable it. */ if (global->netplay.enable) return false; #endif system->frame_time = *info; break; } case RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE: { struct retro_rumble_interface *iface = (struct retro_rumble_interface*)data; RARCH_LOG("Environ GET_RUMBLE_INTERFACE.\n"); iface->set_rumble_state = input_driver_set_rumble_state; break; } case RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES: { uint64_t *mask = (uint64_t*)data; RARCH_LOG("Environ GET_INPUT_DEVICE_CAPABILITIES.\n"); if (driver->input && driver->input->get_capabilities && driver->input_data) *mask = input_driver_get_capabilities(); else return false; break; } case RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE: { struct retro_sensor_interface *iface = (struct retro_sensor_interface*)data; RARCH_LOG("Environ GET_SENSOR_INTERFACE.\n"); iface->set_sensor_state = input_sensor_set_state; iface->get_sensor_input = input_sensor_get_input; break; } case RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE: { struct retro_camera_callback *cb = (struct retro_camera_callback*)data; RARCH_LOG("Environ GET_CAMERA_INTERFACE.\n"); cb->start = driver_camera_start; cb->stop = driver_camera_stop; system->camera_callback = *cb; driver->camera_active = cb->caps != 0; break; } case RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE: { struct retro_location_callback *cb = (struct retro_location_callback*)data; RARCH_LOG("Environ GET_LOCATION_INTERFACE.\n"); cb->start = driver_location_start; cb->stop = driver_location_stop; cb->get_position = driver_location_get_position; cb->set_interval = driver_location_set_interval; system->location_callback = *cb; driver->location_active = true; break; } case RETRO_ENVIRONMENT_GET_LOG_INTERFACE: { struct retro_log_callback *cb = (struct retro_log_callback*)data; RARCH_LOG("Environ GET_LOG_INTERFACE.\n"); cb->log = rarch_log_libretro; break; } case RETRO_ENVIRONMENT_GET_PERF_INTERFACE: { struct retro_perf_callback *cb = (struct retro_perf_callback*)data; RARCH_LOG("Environ GET_PERF_INTERFACE.\n"); cb->get_time_usec = rarch_get_time_usec; cb->get_cpu_features = rarch_get_cpu_features; cb->get_perf_counter = rarch_get_perf_counter; cb->perf_register = retro_perf_register; /* libretro specific path. */ cb->perf_start = rarch_perf_start; cb->perf_stop = rarch_perf_stop; cb->perf_log = retro_perf_log; /* libretro specific path. */ break; } case RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY: { const char **dir = (const char**)data; *dir = *settings->core_assets_directory ? settings->core_assets_directory : NULL; RARCH_LOG("Environ CORE_ASSETS_DIRECTORY: \"%s\".\n", settings->core_assets_directory); break; } case RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO: { RARCH_LOG("Environ SET_SYSTEM_AV_INFO.\n"); return driver_update_system_av_info( (const struct retro_system_av_info*)data); } case RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO: { unsigned i, j; const struct retro_subsystem_info *info = (const struct retro_subsystem_info*)data; RARCH_LOG("Environ SET_SUBSYSTEM_INFO.\n"); for (i = 0; info[i].ident; i++) { RARCH_LOG("Special game type: %s\n", info[i].desc); RARCH_LOG(" Ident: %s\n", info[i].ident); RARCH_LOG(" ID: %u\n", info[i].id); RARCH_LOG(" Content:\n"); for (j = 0; j < info[i].num_roms; j++) { RARCH_LOG(" %s (%s)\n", info[i].roms[j].desc, info[i].roms[j].required ? "required" : "optional"); } } free(system->special); system->special = (struct retro_subsystem_info*) calloc(i, sizeof(*system->special)); if (!system->special) return false; memcpy(system->special, info, i * sizeof(*system->special)); system->num_special = i; break; } case RETRO_ENVIRONMENT_SET_CONTROLLER_INFO: { unsigned i, j; const struct retro_controller_info *info = (const struct retro_controller_info*)data; RARCH_LOG("Environ SET_CONTROLLER_INFO.\n"); for (i = 0; info[i].types; i++) { RARCH_LOG("Controller port: %u\n", i + 1); for (j = 0; j < info[i].num_types; j++) RARCH_LOG(" %s (ID: %u)\n", info[i].types[j].desc, info[i].types[j].id); } free(system->ports); system->ports = (struct retro_controller_info*) calloc(i, sizeof(*system->ports)); if (!system->ports) return false; memcpy(system->ports, info, i * sizeof(*system->ports)); system->num_ports = i; break; } case RETRO_ENVIRONMENT_SET_GEOMETRY: { struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); const struct retro_game_geometry *in_geom = (const struct retro_game_geometry*)data; struct retro_game_geometry *geom = av_info ? (struct retro_game_geometry*)&av_info->geometry : NULL; RARCH_LOG("Environ SET_GEOMETRY.\n"); /* Can potentially be called every frame, * don't do anything unless required. */ if (geom->base_width != in_geom->base_width || geom->base_height != in_geom->base_height || geom->aspect_ratio != in_geom->aspect_ratio) { geom->base_width = in_geom->base_width; geom->base_height = in_geom->base_height; geom->aspect_ratio = in_geom->aspect_ratio; RARCH_LOG("SET_GEOMETRY: %ux%u, aspect: %.3f.\n", geom->base_width, geom->base_height, geom->aspect_ratio); /* Forces recomputation of aspect ratios if * using core-dependent aspect ratios. */ event_command(EVENT_CMD_VIDEO_SET_ASPECT_RATIO); /* TODO: Figure out what to do, if anything, with recording. */ } break; } /* Private extensions for internal use, not part of libretro API. */ case RETRO_ENVIRONMENT_SET_LIBRETRO_PATH: RARCH_LOG("Environ (Private) SET_LIBRETRO_PATH.\n"); if (path_file_exists((const char*)data)) strlcpy(settings->libretro, (const char*)data, sizeof(settings->libretro)); else return false; break; case RETRO_ENVIRONMENT_EXEC: case RETRO_ENVIRONMENT_EXEC_ESCAPE: *global->path.fullpath = '\0'; if (data) strlcpy(global->path.fullpath, (const char*)data, sizeof(global->path.fullpath)); #if defined(RARCH_CONSOLE) if (driver->frontend_ctx && driver->frontend_ctx->set_fork) driver->frontend_ctx->set_fork(true, true); #elif defined(HAVE_DYNAMIC) rarch_main_set_state(RARCH_ACTION_STATE_LOAD_CONTENT); #endif if (cmd == RETRO_ENVIRONMENT_EXEC_ESCAPE) { RARCH_LOG("Environ (Private) EXEC_ESCAPE.\n"); global->exec = true; } else RARCH_LOG("Environ (Private) EXEC.\n"); break; default: RARCH_LOG("Environ UNSUPPORTED (#%u).\n", cmd); return false; } return true; }
void d3d_make_d3dpp(void *data, const video_info_t *info, D3DPRESENT_PARAMETERS *d3dpp) { d3d_video_t *d3d = (d3d_video_t*)data; settings_t *settings = config_get_ptr(); #ifdef _XBOX /* TODO/FIXME - get rid of global state dependencies. */ global_t *global = global_get_ptr(); #endif memset(d3dpp, 0, sizeof(*d3dpp)); d3dpp->Windowed = false; #ifndef _XBOX d3dpp->Windowed = settings->video.windowed_fullscreen || !info->fullscreen; #endif d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; if (info->vsync) { switch (settings->video.swap_interval) { default: case 1: d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_ONE; break; case 2: d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_TWO; break; case 3: d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_THREE; break; case 4: d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_FOUR; break; } } d3dpp->SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp->BackBufferCount = 2; #ifdef _XBOX d3dpp->BackBufferFormat = #ifdef _XBOX360 global->console.screen.gamma_correction ? (D3DFORMAT)MAKESRGBFMT(info->rgb32 ? D3DFMT_X8R8G8B8 : D3DFMT_LIN_R5G6B5) : #endif info->rgb32 ? D3DFMT_X8R8G8B8 : D3DFMT_LIN_R5G6B5; #else d3dpp->hDeviceWindow = win32_get_window(); d3dpp->BackBufferFormat = !d3dpp->Windowed ? D3DFMT_X8R8G8B8 : D3DFMT_UNKNOWN; #endif if (!d3dpp->Windowed) { #ifdef _XBOX unsigned width = 0; unsigned height = 0; gfx_ctx_get_video_size(&width, &height); video_driver_set_size(&width, &height); #endif video_driver_get_size(&d3dpp->BackBufferWidth, &d3dpp->BackBufferHeight); } #ifdef _XBOX d3dpp->MultiSampleType = D3DMULTISAMPLE_NONE; d3dpp->EnableAutoDepthStencil = FALSE; #if defined(_XBOX1) /* Get the "video mode" */ DWORD video_mode = XGetVideoFlags(); /* Check if we are able to use progressive mode. */ if (video_mode & XC_VIDEO_FLAGS_HDTV_480p) d3dpp->Flags = D3DPRESENTFLAG_PROGRESSIVE; else d3dpp->Flags = D3DPRESENTFLAG_INTERLACED; /* Only valid in PAL mode, not valid for HDTV modes. */ if (XGetVideoStandard() == XC_VIDEO_STANDARD_PAL_I) { if (video_mode & XC_VIDEO_FLAGS_PAL_60Hz) d3dpp->FullScreen_RefreshRateInHz = 60; else d3dpp->FullScreen_RefreshRateInHz = 50; } if (XGetAVPack() == XC_AV_PACK_HDTV) { if (video_mode & XC_VIDEO_FLAGS_HDTV_480p) d3dpp->Flags = D3DPRESENTFLAG_PROGRESSIVE; else if (video_mode & XC_VIDEO_FLAGS_HDTV_720p) d3dpp->Flags = D3DPRESENTFLAG_PROGRESSIVE; else if (video_mode & XC_VIDEO_FLAGS_HDTV_1080i) d3dpp->Flags = D3DPRESENTFLAG_INTERLACED; } if (widescreen_mode) d3dpp->Flags |= D3DPRESENTFLAG_WIDESCREEN; #elif defined(_XBOX360) if (!widescreen_mode) d3dpp->Flags |= D3DPRESENTFLAG_NO_LETTERBOX; if (global->console.screen.gamma_correction) d3dpp->FrontBufferFormat = (D3DFORMAT)MAKESRGBFMT(D3DFMT_LE_X8R8G8B8); else d3dpp->FrontBufferFormat = D3DFMT_LE_X8R8G8B8; d3dpp->MultiSampleQuality = 0; #endif #endif }
void menu_video_frame_background( menu_handle_t *menu, settings_t *settings, gl_t *gl, GLuint texture, float handle_alpha, float alpha, bool force_transparency) { struct gfx_coords coords; GRfloat color[16], black_color[16], vertex[8], tex_coord[8]; global_t *global = global_get_ptr(); vertex[0] = 0; vertex[1] = 0; vertex[2] = 1; vertex[3] = 0; vertex[4] = 0; vertex[5] = 1; vertex[6] = 1; vertex[7] = 1; tex_coord[0] = 0; tex_coord[1] = 1; tex_coord[2] = 1; tex_coord[3] = 1; tex_coord[4] = 0; tex_coord[5] = 0; tex_coord[6] = 1; tex_coord[7] = 0; color[ 0] = 1.0f; color[ 1] = 1.0f; color[ 2] = 1.0f; color[ 3] = handle_alpha; color[ 4] = 1.0f; color[ 5] = 1.0f; color[ 6] = 1.0f; color[ 7] = handle_alpha; color[ 8] = 1.0f; color[ 9] = 1.0f; color[10] = 1.0f; color[11] = handle_alpha; color[12] = 1.0f; color[13] = 1.0f; color[14] = 1.0f; color[15] = handle_alpha; if (alpha > handle_alpha) alpha = handle_alpha; black_color[ 0] = 0.0f; black_color[ 1] = 0.0f; black_color[ 2] = 0.0f; black_color[ 3] = alpha; black_color[ 4] = 0.0f; black_color[ 5] = 0.0f; black_color[ 6] = 0.0f; black_color[ 7] = alpha; black_color[ 8] = 0.0f; black_color[ 9] = 0.0f; black_color[10] = 0.0f; black_color[11] = alpha; black_color[12] = 0.0f; black_color[13] = 0.0f; black_color[14] = 0.0f; black_color[15] = alpha; coords.vertices = 4; coords.vertex = vertex; coords.tex_coord = tex_coord; coords.lut_tex_coord = tex_coord; coords.color = black_color; if (gl->shader && gl->shader->use) gl->shader->use(gl, GL_SHADER_STOCK_BLEND); menu_display_set_viewport(); if ((settings->menu.pause_libretro || !global->main_is_init || (global->core_type == CORE_TYPE_DUMMY)) && !force_transparency && texture) coords.color = color; menu_video_draw_frame(gl->shader, &coords, &gl->mvp_no_rot, true, texture); gl->coords.color = gl->white_color_ptr; }