static int database_info_poll(db_handle_t *db) { char elem0[PATH_MAX_LENGTH]; uint32_t cb_type_hash = 0; struct string_list *str_list = NULL; const char *path = msg_queue_pull(db->msg_queue); if (!path) return -1; str_list = string_split(path, "|"); if (!str_list) goto error; if (str_list->size < 1) goto error; strlcpy(elem0, str_list->elems[0].data, sizeof(elem0)); if (str_list->size > 1) cb_type_hash = msg_hash_calculate(str_list->elems[1].data); switch (cb_type_hash) { case CB_DB_SCAN_FILE: db->handle = database_info_file_init(elem0, DATABASE_TYPE_ITERATE); break; case CB_DB_SCAN_FOLDER: db->handle = database_info_dir_init(elem0, DATABASE_TYPE_ITERATE); break; } string_list_free(str_list); return 0; error: if (str_list) string_list_free(str_list); return -1; }
static int rarch_main_data_image_iterate_poll(nbio_handle_t *nbio) { const char *path = NULL; if (!nbio) return -1; path = msg_queue_pull(nbio->image.msg_queue); if (!path) return -1; /* Can only deal with one image transfer at a time for now */ if (nbio->image.handle) return -1; /* We need to load the image file first. */ msg_queue_clear(nbio->msg_queue); msg_queue_push(nbio->msg_queue, path, 0, 1); return 0; }
/** * rarch_main_data_http_iterate_poll: * * Polls HTTP message queue to see if any new URLs * are pending. * * If handle is freed, will set up a new http handle. * The transfer will be started on the next frame. * * Returns: 0 when an URL has been pulled and we will * begin transferring on the next frame. Returns -1 if * no HTTP URL has been pulled. Do nothing in that case. **/ static int rarch_main_data_http_iterate_poll(http_handle_t *http) { char elem0[PATH_MAX_LENGTH]; struct string_list *str_list = NULL; const char *url = msg_queue_pull(http->msg_queue); if (!url) return -1; /* Can only deal with one HTTP transfer at a time for now */ if (http->handle) return -1; str_list = string_split(url, "|"); if (!str_list) return -1; if (str_list->size > 0) strlcpy(elem0, str_list->elems[0].data, sizeof(elem0)); http->connection.handle = net_http_connection_new(elem0); if (!http->connection.handle) return -1; http->connection.cb = &cb_http_conn_default; if (str_list->size > 1) strlcpy(http->connection.elem1, str_list->elems[1].data, sizeof(http->connection.elem1)); string_list_free(str_list); return 0; }
static void xmb_frame(void) { int i; char title_msg[64]; size_t end; const char *dir = NULL; const char *label = NULL; unsigned menu_type = 0; xmb_handle_t *xmb = (xmb_handle_t*)driver.menu->userdata; gl_t *gl = (gl_t*)driver_video_resolve(NULL); if (!xmb || !gl) return; if (driver.menu->need_refresh && g_extern.is_menu && !driver.menu->msg_force) return; update_tweens(0.002); glViewport(0, 0, gl->win_width, gl->win_height); xmb_render_background(); file_list_get_last(driver.menu->menu_stack, &dir, &label, &menu_type); get_title(label, dir, menu_type, xmb->title, sizeof(xmb->title)); xmb_draw_text(xmb->title, 30, 40, 1, 1); const char *core_name = g_extern.menu.info.library_name; if (!core_name) core_name = g_extern.system.info.library_name; if (!core_name) core_name = "No Core"; const char *core_version = g_extern.menu.info.library_version; if (!core_version) core_version = g_extern.system.info.library_version; if (!core_version) core_version = ""; snprintf(title_msg, sizeof(title_msg), "%s - %s %s", PACKAGE_VERSION, core_name, core_version); xmb_draw_text(title_msg, 30, gl->win_height - 30, 1, 1); end = file_list_get_size(driver.menu->selection_buf); for (i = 0; i < end; i++) { char value[PATH_MAX], path_buf[PATH_MAX]; const char *path = NULL, *entry_label = NULL; unsigned type = 0, w = 0; xmb_node_t *node = NULL; file_list_get_at_offset(driver.menu->selection_buf, i, &path, &entry_label, &type); node = (xmb_node_t*)file_list_get_userdata_at_offset( driver.menu->selection_buf, i); disp_set_label(&w, type, i, label, value, sizeof(value), entry_label, path, path_buf, sizeof(path_buf)); xmb_draw_icon(xmb->textures[XMB_TEXTURE_SETTING].id, xmb->margin_left + xmb->hspacing - xmb->icon_size/2.0, xmb->margin_top + node->y + xmb->icon_size/2.0, node->alpha, 0, node->zoom); xmb_draw_text(path_buf, xmb->margin_left + xmb->hspacing + xmb->label_margin_left, xmb->margin_top + node->y + xmb->label_margin_top, 1, node->alpha); xmb_draw_text(value, xmb->margin_left + xmb->hspacing + xmb->label_margin_left + xmb->setting_margin_left, xmb->margin_top + node->y + xmb->label_margin_top, 1, node->alpha); } xmb_draw_icon(xmb->textures[XMB_TEXTURE_SETTINGS].id, xmb->margin_left + xmb->hspacing - xmb->icon_size / 2.0, xmb->margin_top + xmb->icon_size / 2.0, 1.0, 0, 1.0); #ifdef GEKKO const char *message_queue; if (driver.menu->msg_force) { message_queue = msg_queue_pull(g_extern.msg_queue); driver.menu->msg_force = false; } else message_queue = driver.current_msg; xmb_render_messagebox(message_queue); #endif if (driver.menu->keyboard.display) { char msg[PATH_MAX]; const char *str = *driver.menu->keyboard.buffer; if (!str) str = ""; snprintf(msg, sizeof(msg), "%s\n%s", driver.menu->keyboard.label, str); xmb_render_messagebox(msg); } if (xmb->box_message[0] != '\0') { xmb_render_background(); xmb_render_messagebox(xmb->box_message); xmb->box_message[0] = '\0'; } gl_set_viewport(gl, gl->win_width, gl->win_height, false, false); }
bool runloop_ctl(enum runloop_ctl_state state, void *data) { switch (state) { case RUNLOOP_CTL_SHADER_DIR_DEINIT: shader_dir_free(&runloop_shader_dir); break; case RUNLOOP_CTL_SHADER_DIR_INIT: return shader_dir_init(&runloop_shader_dir); case RUNLOOP_CTL_SYSTEM_INFO_INIT: core_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"; video_driver_set_title_buf(); strlcpy(runloop_system.valid_extensions, runloop_system.info.valid_extensions ? runloop_system.info.valid_extensions : DEFAULT_EXT, sizeof(runloop_system.valid_extensions)); break; case RUNLOOP_CTL_GET_CORE_OPTION_SIZE: { unsigned *idx = (unsigned*)data; if (!idx) return false; *idx = core_option_manager_size(runloop_core_options); } break; case RUNLOOP_CTL_HAS_CORE_OPTIONS: return runloop_core_options; case RUNLOOP_CTL_CORE_OPTIONS_LIST_GET: { core_option_manager_t **coreopts = (core_option_manager_t**)data; if (!coreopts) return false; *coreopts = runloop_core_options; } break; case RUNLOOP_CTL_SYSTEM_INFO_GET: { rarch_system_info_t **system = (rarch_system_info_t**)data; if (!system) return false; *system = &runloop_system; } break; case RUNLOOP_CTL_SYSTEM_INFO_FREE: /* No longer valid. */ if (runloop_system.subsystem.data) free(runloop_system.subsystem.data); runloop_system.subsystem.data = NULL; runloop_system.subsystem.size = 0; if (runloop_system.ports.data) free(runloop_system.ports.data); runloop_system.ports.data = NULL; runloop_system.ports.size = 0; if (runloop_system.mmaps.descriptors) free((void *)runloop_system.mmaps.descriptors); runloop_system.mmaps.descriptors = NULL; runloop_system.mmaps.num_descriptors = 0; runloop_key_event = NULL; runloop_frontend_key_event = NULL; audio_driver_unset_callback(); memset(&runloop_system, 0, sizeof(rarch_system_info_t)); break; case RUNLOOP_CTL_SET_FRAME_TIME_LAST: runloop_frame_time_last_enable = true; break; case RUNLOOP_CTL_UNSET_FRAME_TIME_LAST: if (!runloop_ctl(RUNLOOP_CTL_IS_FRAME_TIME_LAST, NULL)) return false; runloop_frame_time_last = 0; runloop_frame_time_last_enable = 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_enable; 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; } break; 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_SET_NONBLOCK_FORCED: runloop_force_nonblock = true; break; case RUNLOOP_CTL_UNSET_NONBLOCK_FORCED: runloop_force_nonblock = false; break; case RUNLOOP_CTL_IS_NONBLOCK_FORCED: return runloop_force_nonblock; case RUNLOOP_CTL_SET_FRAME_TIME: { const struct retro_frame_time_callback *info = (const struct retro_frame_time_callback*)data; #ifdef HAVE_NETPLAY global_t *global = global_get_ptr(); /* retro_run() will be called in very strange and * mysterious ways, have to disable it. */ if (global->netplay.enable) return false; #endif runloop_frame_time = *info; } break; 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; config_set_active_core_path(fullpath); } 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_CLEAR_DEFAULT_SHADER_PRESET: *runloop_default_shader_preset = '\0'; break; case RUNLOOP_CTL_GET_DEFAULT_SHADER_PRESET: { char **preset = (char**)data; if (!preset) return false; *preset = (char*)runloop_default_shader_preset; } break; case RUNLOOP_CTL_SET_DEFAULT_SHADER_PRESET: { const char *preset = (const char*)data; if (!preset) return false; strlcpy(runloop_default_shader_preset, preset, sizeof(runloop_default_shader_preset)); } break; case RUNLOOP_CTL_FRAME_TIME_FREE: memset(&runloop_frame_time, 0, sizeof(struct retro_frame_time_callback)); runloop_frame_time_last = 0; runloop_max_frames = 0; break; case RUNLOOP_CTL_STATE_FREE: runloop_perfcnt_enable = false; runloop_idle = false; runloop_paused = false; runloop_slowmotion = false; runloop_frame_time_last_enable = false; runloop_set_frame_limit = false; runloop_overrides_active = false; runloop_ctl(RUNLOOP_CTL_FRAME_TIME_FREE, NULL); break; case RUNLOOP_CTL_GLOBAL_FREE: { global_t *global = NULL; command_event(CMD_EVENT_TEMPORARY_CONTENT_DEINIT, NULL); command_event(CMD_EVENT_SUBSYSTEM_FULLPATHS_DEINIT, NULL); command_event(CMD_EVENT_RECORD_DEINIT, NULL); command_event(CMD_EVENT_LOG_FILE_DEINIT, NULL); rarch_ctl(RARCH_CTL_UNSET_BLOCK_CONFIG_READ, NULL); runloop_ctl(RUNLOOP_CTL_CLEAR_CONTENT_PATH, NULL); runloop_overrides_active = false; core_unset_input_descriptors(); global = global_get_ptr(); memset(global, 0, sizeof(struct global)); config_free_state(); } 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: return runloop_slowmotion; 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_PULL: runloop_msg_queue_lock(); { const char **ret = (const char**)data; if (!ret) return false; *ret = msg_queue_pull(runloop_msg_queue); } runloop_msg_queue_unlock(); break; 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_CLEAR: msg_queue_clear(runloop_msg_queue); break; case RUNLOOP_CTL_MSG_QUEUE_DEINIT: if (!runloop_msg_queue) return true; runloop_msg_queue_lock(); msg_queue_free(runloop_msg_queue); runloop_msg_queue_unlock(); runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_FREE, NULL); runloop_msg_queue = NULL; break; case RUNLOOP_CTL_MSG_QUEUE_INIT: runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_DEINIT, NULL); runloop_msg_queue = msg_queue_new(8); retro_assert(runloop_msg_queue); #ifdef HAVE_THREADS _runloop_msg_queue_lock = slock_new(); retro_assert(_runloop_msg_queue_lock); #endif break; case RUNLOOP_CTL_TASK_INIT: { #ifdef HAVE_THREADS settings_t *settings = config_get_ptr(); bool threaded_enable = settings->threaded_data_runloop_enable; #else bool threaded_enable = false; #endif task_queue_ctl(TASK_QUEUE_CTL_DEINIT, NULL); task_queue_ctl(TASK_QUEUE_CTL_INIT, &threaded_enable); } 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: task_queue_ctl(TASK_QUEUE_CTL_DEINIT, NULL); break; case RUNLOOP_CTL_IS_CORE_OPTION_UPDATED: if (!runloop_core_options) return false; return core_option_manager_updated(runloop_core_options); case RUNLOOP_CTL_CORE_OPTION_PREV: { unsigned *idx = (unsigned*)data; if (!idx) return false; core_option_manager_prev(runloop_core_options, *idx); if (ui_companion_is_on_foreground()) ui_companion_driver_notify_refresh(); } break; case RUNLOOP_CTL_CORE_OPTION_NEXT: { unsigned *idx = (unsigned*)data; if (!idx) return false; core_option_manager_next(runloop_core_options, *idx); if (ui_companion_is_on_foreground()) ui_companion_driver_notify_refresh(); } break; case RUNLOOP_CTL_CORE_OPTIONS_GET: { struct retro_variable *var = (struct retro_variable*)data; if (!runloop_core_options || !var) return false; RARCH_LOG("Environ GET_VARIABLE %s:\n", var->key); core_option_manager_get(runloop_core_options, var); RARCH_LOG("\t%s\n", var->value ? var->value : msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE)); } break; case RUNLOOP_CTL_CORE_OPTIONS_INIT: { char *game_options_path = NULL; bool ret = false; char buf[PATH_MAX_LENGTH] = {0}; global_t *global = global_get_ptr(); settings_t *settings = config_get_ptr(); const char *options_path = settings->path.core_options; const struct retro_variable *vars = (const struct retro_variable*)data; if (string_is_empty(options_path) && !string_is_empty(global->path.config)) { fill_pathname_resolve_relative(buf, global->path.config, file_path_str(FILE_PATH_CORE_OPTIONS_CONFIG), 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_core_options = core_option_manager_new(game_options_path, vars); free(game_options_path); } else { runloop_ctl(RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE, NULL); runloop_core_options = core_option_manager_new(options_path, vars); } } break; case RUNLOOP_CTL_CORE_OPTIONS_FREE: if (runloop_core_options) core_option_manager_free(runloop_core_options); runloop_core_options = NULL; break; case RUNLOOP_CTL_CORE_OPTIONS_DEINIT: { global_t *global = global_get_ptr(); if (!runloop_core_options) return false; /* check if game options file was just created and flush to that file instead */ if(global && !string_is_empty(global->path.core_options_path)) { core_option_manager_flush_game_specific(runloop_core_options, global->path.core_options_path); global->path.core_options_path[0] = '\0'; } else core_option_manager_flush(runloop_core_options); if (runloop_ctl(RUNLOOP_CTL_IS_GAME_OPTIONS_ACTIVE, NULL)) runloop_ctl(RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE, NULL); runloop_ctl(RUNLOOP_CTL_CORE_OPTIONS_FREE, NULL); } break; 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_FRONTEND_KEY_EVENT_GET: { retro_keyboard_event_t **key_event = (retro_keyboard_event_t**)data; if (!key_event) return false; *key_event = &runloop_frontend_key_event; } break; case RUNLOOP_CTL_HTTPSERVER_INIT: #if defined(HAVE_HTTPSERVER) && defined(HAVE_ZLIB) httpserver_init(8888); #endif break; case RUNLOOP_CTL_HTTPSERVER_DESTROY: #if defined(HAVE_HTTPSERVER) && defined(HAVE_ZLIB) httpserver_destroy(); #endif break; case RUNLOOP_CTL_NONE: default: break; } return true; }
bool rmenu_iterate(void) { static bool preinit = true; const char *msg; xdk_d3d_video_t *device_ptr = (xdk_d3d_video_t*)driver.video_data; if(preinit) { g_extern.console.rmenu.input_loop = INPUT_LOOP_MENU; g_extern.draw_menu = true; preinit = false; } g_extern.frame_count++; XINPUT_STATE state; XInputGetState(0, &state); bool rmenu_enable = !((state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) && (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) && (g_extern.console.emulator_initialized) && IS_TIMER_EXPIRED(0)); rarch_render_cached_frame(); g_extern.console.rmenu.mode = rmenu_enable ? MODE_MENU : MODE_EMULATION; switch(g_extern.console.rmenu.input_loop) { case INPUT_LOOP_FILEBROWSER: case INPUT_LOOP_MENU: app.RunFrame(); /* Update XUI */ if((state.Gamepad.wButtons & XINPUT_GAMEPAD_B) && hCur != app.hMainScene) XuiSceneNavigateBack(hCur, app.hMainScene, XUSER_INDEX_ANY); break; case INPUT_LOOP_RESIZE_MODE: ingame_menu_resize(); break; default: break; } if(g_extern.console.rmenu.mode == MODE_EMULATION || g_extern.console.rmenu.mode == MODE_EXIT) goto deinit; msg = msg_queue_pull(g_extern.msg_queue); if (msg) { device_ptr->font_ctx->render_msg(device_ptr, msg); } device_ptr->ctx_driver->swap_buffers(); return true; deinit: if(!(g_extern.lifecycle_state & (1ULL << RARCH_FRAMEADVANCE))) { // set a timer delay so that we don't instantly switch back to the menu when // press and holding L3 + R3 in the emulation loop (lasts for 30 frame ticks) SET_TIMER_EXPIRATION(0, 30); } g_extern.console.rmenu.state.ingame_menu.enable = false; g_extern.draw_menu = false; preinit = true; return false; }
static int rarch_main_data_nbio_iterate_poll(nbio_handle_t *nbio) { char elem0[PATH_MAX_LENGTH]; unsigned elem0_hash = 0; uint32_t cb_type_hash = 0; struct nbio_t* handle = NULL; struct string_list *str_list = NULL; const char *path = NULL; if (!nbio) return -1; path = msg_queue_pull(nbio->msg_queue); if (!path) return -1; /* Can only deal with one NBIO transfer at a time for now */ if (nbio->handle) return -1; str_list = string_split(path, "|"); if (!str_list || (str_list->size < 1)) goto error; strlcpy(elem0, str_list->elems[0].data, sizeof(elem0)); elem0_hash = djb2_calculate(elem0); /* TODO/FIXME - should be able to deal with this * in a better way. */ switch(elem0_hash) { case CB_MENU_WALLPAPER: case CB_MENU_BOXART: goto error; default: break; } if (str_list->size > 1) cb_type_hash = djb2_calculate(str_list->elems[1].data); handle = nbio_open(elem0, NBIO_READ); if (!handle) { RARCH_ERR("Could not create new file loading handle.\n"); goto error; } nbio->handle = handle; nbio->is_finished = false; nbio->cb = &cb_nbio_default; switch (cb_type_hash) { #if defined(HAVE_MENU) && defined(HAVE_RPNG) case CB_MENU_WALLPAPER: nbio->cb = &cb_nbio_image_menu_wallpaper; break; case CB_MENU_BOXART: nbio->cb = &cb_nbio_image_menu_boxart; break; #endif } nbio_begin_read(handle); string_list_free(str_list); return 0; error: if (str_list) string_list_free(str_list); return -1; }
static int rarch_main_data_nbio_iterate_poll(nbio_handle_t *nbio) { struct nbio_t* handle; char elem0[PATH_MAX_LENGTH], elem1[PATH_MAX_LENGTH]; struct string_list *str_list = NULL; const char *path = NULL; if (!nbio) return -1; path = msg_queue_pull(nbio->msg_queue); if (!path) return -1; /* Can only deal with one NBIO transfer at a time for now */ if (nbio->handle) return -1; str_list = string_split(path, "|"); if (!str_list) goto error; if (str_list->size > 0) strlcpy(elem0, str_list->elems[0].data, sizeof(elem0)); if (str_list->size > 1) strlcpy(elem1, str_list->elems[1].data, sizeof(elem1)); handle = nbio_open(elem0, NBIO_READ); if (!handle) { RARCH_ERR("Could not create new file loading handle.\n"); goto error; } nbio->handle = handle; nbio->is_blocking = false; nbio->is_finished = false; nbio->cb = &cb_nbio_default; if (elem1[0] != '\0') { #ifdef HAVE_MENU if (!strcmp(elem1, "cb_menu_wallpaper")) nbio->cb = &cb_nbio_image_menu_wallpaper; #endif } nbio_begin_read(handle); string_list_free(str_list); return 0; error: if (str_list) string_list_free(str_list); return -1; }
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 retro_keyboard_event_t runloop_frontend_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 msg_queue_t *runloop_msg_queue = NULL; settings_t *settings = config_get_ptr(); switch (state) { case RUNLOOP_CTL_DATA_ITERATE: task_queue_ctl(TASK_QUEUE_CTL_CHECK, NULL); break; case RUNLOOP_CTL_SHADER_DIR_DEINIT: shader_dir_free(&runloop_shader_dir); break; case RUNLOOP_CTL_SHADER_DIR_INIT: return shader_dir_init(&runloop_shader_dir); case RUNLOOP_CTL_SYSTEM_INFO_INIT: core_ctl(CORE_CTL_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"; 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)); 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); } break; case RUNLOOP_CTL_HAS_CORE_OPTIONS: return runloop_system.core_options; case RUNLOOP_CTL_SYSTEM_INFO_GET: { rarch_system_info_t **system = (rarch_system_info_t**)data; if (!system) return false; *system = &runloop_system; } break; 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; runloop_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; } break; 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); break; 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_cmd_ctl(EVENT_CMD_TAKE_SCREENSHOT, NULL); if (runloop_cmd_triggered(cmd, RARCH_MUTE)) event_cmd_ctl(EVENT_CMD_AUDIO_MUTE_TOGGLE, NULL); 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_cmd_ctl(EVENT_CMD_VOLUME_UP, NULL); else if (runloop_cmd_press(cmd, RARCH_VOLUME_DOWN)) event_cmd_ctl(EVENT_CMD_VOLUME_DOWN, NULL); #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_cmd_ctl(EVENT_CMD_SAVE_STATE, NULL); else if (runloop_cmd_triggered(cmd, RARCH_LOAD_STATE_KEY)) event_cmd_ctl(EVENT_CMD_LOAD_STATE, NULL); 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_cmd_ctl(EVENT_CMD_DISK_EJECT_TOGGLE, NULL); else if (runloop_cmd_triggered(cmd, RARCH_DISK_NEXT)) event_cmd_ctl(EVENT_CMD_DISK_NEXT, NULL); else if (runloop_cmd_triggered(cmd, RARCH_DISK_PREV)) event_cmd_ctl(EVENT_CMD_DISK_PREV, NULL); if (runloop_cmd_triggered(cmd, RARCH_RESET)) event_cmd_ctl(EVENT_CMD_RESET, NULL); 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_cmd_ctl(EVENT_CMD_FULLSCREEN_TOGGLE, NULL); 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(msg_hash_to_str(MSG_SLOW_MOTION_REWIND), 0, 30, true); else runloop_msg_queue_push(msg_hash_to_str(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( msg_hash_to_str(MSG_MOVIE_RECORD_STOPPED), 2, 180, true); RARCH_LOG("%s\n", msg_hash_to_str(MSG_MOVIE_RECORD_STOPPED)); event_cmd_ctl(EVENT_CMD_BSV_MOVIE_DEINIT, NULL); 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( msg_hash_to_str(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( msg_hash_to_str(MSG_MOVIE_PLAYBACK_ENDED), 1, 180, false); RARCH_LOG("%s\n", msg_hash_to_str(MSG_MOVIE_PLAYBACK_ENDED)); event_cmd_ctl(EVENT_CMD_BSV_MOVIE_DEINIT, NULL); 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 = NULL; event_cmd_ctl(EVENT_CMD_TEMPORARY_CONTENT_DEINIT, NULL); event_cmd_ctl(EVENT_CMD_SUBSYSTEM_FULLPATHS_DEINIT, NULL); event_cmd_ctl(EVENT_CMD_RECORD_DEINIT, NULL); event_cmd_ctl(EVENT_CMD_LOG_FILE_DEINIT, NULL); 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_PUSH: { runloop_ctx_msg_info_t *msg_info = (runloop_ctx_msg_info_t*)data; if (!msg_info || !runloop_msg_queue) return false; msg_queue_push(runloop_msg_queue, msg_info->msg, msg_info->prio, msg_info->duration); if (ui_companion_is_on_foreground()) { const ui_companion_driver_t *ui = ui_companion_get_ptr(); if (ui->msg_queue_push) ui->msg_queue_push(msg_info->msg, msg_info->prio, msg_info->duration, msg_info->flush); } } break; case RUNLOOP_CTL_MSG_QUEUE_PULL: { const char **ret = (const char**)data; if (!ret) return false; *ret = msg_queue_pull(runloop_msg_queue); } break; 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_CLEAR: msg_queue_clear(runloop_msg_queue); break; case RUNLOOP_CTL_MSG_QUEUE_DEINIT: if (!runloop_msg_queue) return true; runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_LOCK, NULL); msg_queue_free(runloop_msg_queue); runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_UNLOCK, NULL); runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_FREE, NULL); runloop_msg_queue = NULL; break; case RUNLOOP_CTL_MSG_QUEUE_INIT: runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_DEINIT, NULL); runloop_msg_queue = msg_queue_new(8); retro_assert(runloop_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_TASK_INIT: { bool threaded_enable = false; #ifdef HAVE_THREADS threaded_enable = settings->threaded_data_runloop_enable; #endif task_queue_ctl(TASK_QUEUE_CTL_INIT, &threaded_enable); } break; case RUNLOOP_CTL_PREPARE_DUMMY: #ifdef HAVE_MENU menu_driver_ctl(RARCH_MENU_CTL_UNSET_LOAD_NO_CONTENT, NULL); #endif runloop_ctl(RUNLOOP_CTL_DATA_DEINIT, NULL); runloop_ctl(RUNLOOP_CTL_TASK_INIT, NULL); 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: task_queue_ctl(TASK_QUEUE_CTL_DEINIT, NULL); break; case RUNLOOP_CTL_IS_CORE_OPTION_UPDATED: if (!runloop_system.core_options) return false; return core_option_updated(runloop_system.core_options); 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(); } break; 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(); } break; 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"); } break; case RUNLOOP_CTL_CORE_OPTIONS_INIT: { char *game_options_path = NULL; bool ret = false; char buf[PATH_MAX_LENGTH] = {0}; global_t *global = global_get_ptr(); const char *options_path = settings->core_options_path; const struct retro_variable *vars = (const struct retro_variable*)data; 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; /* check if game options file was just created and flush to that file instead */ if(!string_is_empty(runloop_system.game_options_path)) { core_option_flush_game_specific(runloop_system.core_options, runloop_system.game_options_path); runloop_system.game_options_path[0] = '\0'; } else core_option_flush(runloop_system.core_options); core_option_free(runloop_system.core_options); if (runloop_ctl(RUNLOOP_CTL_IS_GAME_OPTIONS_ACTIVE, NULL)) runloop_ctl(RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE, NULL); runloop_system.core_options = NULL; break; 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_FRONTEND_KEY_EVENT_GET: { retro_keyboard_event_t **key_event = (retro_keyboard_event_t**)data; if (!key_event) return false; *key_event = &runloop_frontend_key_event; } break; case RUNLOOP_CTL_NONE: default: break; } return true; }
static void glui_frame(void) { unsigned x, y; size_t i; char title[PATH_MAX], title_buf[PATH_MAX], title_msg[PATH_MAX]; const char *dir = NULL; const char *label = NULL; unsigned menu_type = 0; size_t end; gl_t *gl = (gl_t*)driver_video_resolve(NULL); glui_handle_t *glui = NULL; if (!driver.menu || !gl) return; glui = (glui_handle_t*)driver.menu->userdata; if (!glui) return; if (driver.menu->need_refresh && g_extern.is_menu && !driver.menu->msg_force) return; glui->line_height = g_settings.video.font_size * 4 / 3; glui->glyph_width = glui->line_height / 2; glui->margin = gl->win_width / 20 ; glui->term_width = (gl->win_width - glui->margin * 2) / glui->glyph_width; glui->term_height = (gl->win_height - glui->margin * 2) / glui->line_height - 2; driver.menu->mouse.ptr = (driver.menu->mouse.y - glui->margin) / glui->line_height - 2 + driver.menu->begin; glViewport(0, 0, gl->win_width, gl->win_height); if (driver.menu->mouse.wheeldown && driver.menu->begin < menu_list_get_size(driver.menu->menu_list) - glui->term_height) driver.menu->begin++; if (driver.menu->mouse.wheelup && driver.menu->begin > 0) driver.menu->begin--; /* Do not scroll if all items are visible. */ if (menu_list_get_size(driver.menu->menu_list) <= glui->term_height) driver.menu->begin = 0; end = (driver.menu->begin + glui->term_height <= menu_list_get_size(driver.menu->menu_list)) ? driver.menu->begin + glui->term_height : menu_list_get_size(driver.menu->menu_list); glui_render_background(false); menu_list_get_last_stack(driver.menu->menu_list, &dir, &label, &menu_type); get_title(label, dir, menu_type, title, sizeof(title)); menu_ticker_line(title_buf, glui->term_width - 3, g_extern.frame_count / glui->margin, title, true); glui_blit_line(glui->margin * 2, glui->margin + glui->line_height, title_buf, true); const char *core_name = g_extern.menu.info.library_name; if (!core_name) core_name = g_extern.system.info.library_name; if (!core_name) core_name = "No Core"; const char *core_version = g_extern.menu.info.library_version; if (!core_version) core_version = g_extern.system.info.library_version; if (!core_version) core_version = ""; snprintf(title_msg, sizeof(title_msg), "%s - %s %s", PACKAGE_VERSION, core_name, core_version); glui_blit_line( glui->margin * 2, glui->margin + glui->term_height * glui->line_height + glui->line_height * 2, title_msg, true); x = glui->margin; y = glui->margin + glui->line_height * 2; for (i = driver.menu->begin; i < end; i++, y += glui->line_height) { char message[PATH_MAX], type_str[PATH_MAX], entry_title_buf[PATH_MAX], type_str_buf[PATH_MAX], path_buf[PATH_MAX]; const char *path = NULL, *entry_label = NULL; unsigned type = 0, w = 0; bool selected = false; menu_list_get_at_offset(driver.menu->menu_list->selection_buf, i, &path, &entry_label, &type); rarch_setting_t *setting = (rarch_setting_t*)setting_data_find_setting( driver.menu->list_settings, driver.menu->menu_list->selection_buf->list[i].label); (void)setting; disp_set_label(driver.menu->menu_list->selection_buf, &w, type, i, label, type_str, sizeof(type_str), entry_label, path, path_buf, sizeof(path_buf)); selected = (i == driver.menu->selection_ptr); menu_ticker_line(entry_title_buf, glui->term_width - (w + 1 + 2), g_extern.frame_count / glui->margin, path_buf, selected); menu_ticker_line(type_str_buf, w, g_extern.frame_count / glui->margin, type_str, selected); strlcpy(message, entry_title_buf, sizeof(message)); glui_blit_line(x, y, message, selected); glui_blit_line(gl->win_width - glui->glyph_width * w - glui->margin , y, type_str_buf, selected); } #ifdef GEKKO const char *message_queue; if (driver.menu->msg_force) { message_queue = msg_queue_pull(g_extern.msg_queue); driver.menu->msg_force = false; } else message_queue = driver.current_msg; glui_render_messagebox(message_queue); #endif if (driver.menu->keyboard.display) { char msg[PATH_MAX]; const char *str = *driver.menu->keyboard.buffer; if (!str) str = ""; glui_render_background(true); snprintf(msg, sizeof(msg), "%s\n%s", driver.menu->keyboard.label, str); glui_render_messagebox(msg); } if (glui->box_message[0] != '\0') { glui_render_background(true); glui_render_messagebox(glui->box_message); glui->box_message[0] = '\0'; } if (driver.menu->mouse.enable) glui_draw_cursor(driver.menu->mouse.x, driver.menu->mouse.y); gl_set_viewport(gl, gl->win_width, gl->win_height, false, false); }
void menu_loop(void) { HRESULT hr; xdk_d3d_video_t *d3d = (xdk_d3d_video_t*)driver.video_data; g_extern.console.rmenu.state.rmenu.enable = true; d3d->block_swap = true; g_extern.console.rmenu.input_loop = INPUT_LOOP_MENU; do { if(g_extern.console.emulator_initialized) rarch_render_cached_frame(); else { d3d->d3d_render_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0); d3d->frame_count++; } XINPUT_STATE state; XInputGetState(0, &state); g_extern.console.rmenu.state.rmenu.enable = !((state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) && (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) && (g_extern.console.emulator_initialized) && IS_TIMER_EXPIRED(d3d)); g_extern.console.rmenu.mode = g_extern.console.rmenu.state.rmenu.enable ? MODE_MENU : MODE_EMULATION; switch(g_extern.console.rmenu.input_loop) { case INPUT_LOOP_FILEBROWSER: /* if(((state.Gamepad.wButtons & XINPUT_GAMEPAD_Y) && hCur != app.hMainScene)) { uint64_t action = (1 << RMENU_DEVICE_NAV_A); browser_update(browser, action, rarch_console_get_rom_ext()); SET_TIMER_EXPIRATION(d3d, 15); } */ case INPUT_LOOP_MENU: app.RunFrame(); /* Update XUI */ if((state.Gamepad.wButtons & XINPUT_GAMEPAD_B) && hCur != app.hMainScene) XuiSceneNavigateBack(hCur, app.hMainScene, XUSER_INDEX_ANY); break; case INPUT_LOOP_RESIZE_MODE: ingame_menu_resize(); break; default: break; } hr = app.Render(); /* Render XUI */ hr = XuiTimersRun(); /* Update XUI timers */ if(g_extern.console.rmenu.mode == MODE_EMULATION && !g_extern.console.screen.state.frame_advance.enable) { SET_TIMER_EXPIRATION(d3d, 30); } const char *message = msg_queue_pull(g_extern.msg_queue); if (message) { xdk360_console_format(message); xdk360_console_draw(); } context->swap_buffers(); }while(g_extern.console.rmenu.state.rmenu.enable); d3d->block_swap = false; g_extern.console.rmenu.state.ingame_menu.enable = false; }
void menu_loop(void) { HRESULT hr; xdk360_video_t *d3d9 = (xdk360_video_t*)driver.video_data; g_console.menu_enable = true; d3d9->block_swap = true; g_console.input_loop = INPUT_LOOP_MENU; do { if(g_console.emulator_initialized) { rarch_render_cached_frame(); } else { d3d9->d3d_render_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0); d3d9->frame_count++; } XINPUT_STATE state; XInputGetState(0, &state); g_console.menu_enable = !((state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) && (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) && (g_console.emulator_initialized) && IS_TIMER_EXPIRED(d3d9)); g_console.mode_switch = g_console.menu_enable ? MODE_MENU : MODE_EMULATION; switch(g_console.input_loop) { case INPUT_LOOP_MENU: app.RunFrame(); /* Update XUI */ if(state.Gamepad.wButtons & XINPUT_GAMEPAD_B && hCur != app.hMainScene) XuiSceneNavigateBack(hCur, app.hMainScene, XUSER_INDEX_ANY); break; case INPUT_LOOP_RESIZE_MODE: ingame_menu_resize(); break; default: break; } hr = app.Render(); /* Render XUI */ hr = XuiTimersRun(); /* Update XUI timers */ if(g_console.mode_switch == MODE_EMULATION && !g_console.frame_advance_enable) { SET_TIMER_EXPIRATION(d3d9, 30); } const char *message = msg_queue_pull(g_extern.msg_queue); if (message) { if(IS_TIMER_EXPIRED(d3d9)) { xdk360_console_format(message); SET_TIMER_EXPIRATION(d3d9, 30); } xdk360_console_draw(); } gfx_ctx_swap_buffers(); }while(g_console.menu_enable); d3d9->block_swap = false; g_console.ingame_menu_enable = false; }