/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2013 - Hans-Kristian Arntzen
* Copyright (C) 2011-2013 - Daniel De Matteis
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see .
*/
#include "rmenu.h"
#include "file_browser.h"
#if defined(__CELLOS_LV2__)
#include
#if (CELL_SDK_VERSION > 0x340000)
#include
#endif
#endif
#include "../../console/rarch_console.h"
#include "../../gfx/image.h"
#include "../../gfx/gfx_common.h"
#include "../../gfx/gfx_context.h"
#include "../../file.h"
#include "../../driver.h"
#include "../../general.h"
#ifdef HAVE_SHADER_MANAGER
#include "../../gfx/shader_parse.h"
#define EXT_SHADERS "cg"
#define EXT_CGP_PRESETS "cgp"
#endif
#ifdef _XBOX1
#define JPEG_FORMATS ""
#else
#define JPEG_FORMATS "|jpg|JPG|JPEG|jpeg"
#endif
#define EXT_IMAGES "png|PNG"JPEG_FORMATS
struct texture_image *menu_texture;
#ifdef HAVE_MENU_PANEL
struct texture_image *menu_panel;
#endif
#if defined(_XBOX1)
const char drive_mappings[][32] = {
"C:\\",
"D:\\",
"E:\\",
"F:\\",
"G:\\"
};
size_t drive_mapping_idx = 2;
#define TICKER_LABEL_CHARS_MAX_PER_LINE 16
#elif defined(__CELLOS_LV2__)
const char drive_mappings[][32] = {
"/app_home/",
"/dev_hdd0/",
"/dev_hdd1/",
"/host_root/"
};
size_t drive_mapping_idx = 1;
#define TICKER_LABEL_CHARS_MAX_PER_LINE 25
#endif
unsigned settings_lut[SETTING_LAST_LAST] = {0};
static const char *menu_drive_mapping_previous(void)
{
if (drive_mapping_idx > 0)
drive_mapping_idx--;
return drive_mappings[drive_mapping_idx];
}
static const char *menu_drive_mapping_next(void)
{
size_t arr_size = sizeof(drive_mappings) / sizeof(drive_mappings[0]);
if ((drive_mapping_idx + 1) < arr_size)
drive_mapping_idx++;
return drive_mappings[drive_mapping_idx];
}
#ifdef HAVE_SHADER_MANAGER
static void shader_manager_get_str_filter(char *type_str,
size_t sizeof_type_str, unsigned pass)
{
switch (rgui->shader.pass[pass].filter)
{
case RARCH_FILTER_LINEAR:
strlcpy(type_str, "Linear", sizeof_type_str);
break;
case RARCH_FILTER_NEAREST:
strlcpy(type_str, "Nearest", sizeof_type_str);
break;
case RARCH_FILTER_UNSPEC:
strlcpy(type_str, "Don't care", sizeof_type_str);
break;
}
}
#endif
/*============================================================
MENU STACK
============================================================ */
static unsigned char menu_stack_enum_array[10];
static unsigned stack_idx = 0;
static unsigned shader_choice_set_shader_slot = 0;
static unsigned setting_page_number = 0;
static void menu_stack_pop(unsigned menu_type)
{
switch(menu_type)
{
case LIBRETRO_CHOICE:
case INGAME_MENU_CORE_OPTIONS:
case INGAME_MENU_LOAD_GAME_HISTORY:
case INGAME_MENU_CUSTOM_RATIO:
case INGAME_MENU_SCREENSHOT:
rgui->frame_buf_show = true;
break;
case INGAME_MENU_SETTINGS:
case INGAME_MENU_VIDEO_OPTIONS:
case INGAME_MENU_AUDIO_OPTIONS:
case INGAME_MENU_INPUT_OPTIONS:
case INGAME_MENU_PATH_OPTIONS:
rgui->selection_ptr = FIRST_INGAME_MENU_SETTING;
rgui->frame_buf_show = true;
break;
case INGAME_MENU_SHADER_OPTIONS:
rgui->selection_ptr = FIRST_VIDEO_SETTING;
break;
#ifdef HAVE_SHADER_MANAGER
case CGP_CHOICE:
rgui->selection_ptr = FIRST_SHADERMAN_SETTING;
break;
#endif
default:
break;
}
setting_page_number = 0;
if (rgui->browser->prev_dir.directory_path[0] != '\0')
{
memcpy(&rgui->browser->current_dir, &rgui->browser->prev_dir, sizeof(*(&rgui->browser->current_dir)));
filebrowser_reset_current_dir(rgui->browser);
rgui->browser->current_dir.ptr = rgui->browser->prev_dir.ptr;
strlcpy(rgui->browser->current_dir.path, rgui->browser->prev_dir.path,
sizeof(rgui->browser->current_dir.path));
memset(&rgui->browser->prev_dir, 0, sizeof(*(&rgui->browser->prev_dir)));
}
if (stack_idx > 1)
stack_idx--;
}
static void menu_stack_push(unsigned menu_type, bool prev_dir)
{
switch (menu_type)
{
case INGAME_MENU:
rgui->selection_ptr = FIRST_INGAME_MENU_SETTING;
break;
case INGAME_MENU_VIDEO_OPTIONS:
rgui->selection_ptr = FIRST_VIDEO_SETTING;
break;
#ifdef HAVE_SHADER_MANAGER
case INGAME_MENU_SHADER_OPTIONS:
rgui->selection_ptr = FIRST_SHADERMAN_SETTING;
break;
#endif
case INGAME_MENU_AUDIO_OPTIONS:
rgui->selection_ptr = FIRST_AUDIO_SETTING;
break;
case INGAME_MENU_INPUT_OPTIONS:
rgui->selection_ptr = FIRST_CONTROLS_SETTING_PAGE_1;
break;
case INGAME_MENU_PATH_OPTIONS:
rgui->selection_ptr = FIRST_PATH_SETTING;
break;
case INGAME_MENU_SETTINGS:
rgui->selection_ptr = FIRST_SETTING;
break;
default:
break;
}
setting_page_number = 0;
if (prev_dir)
{
memcpy(&rgui->browser->prev_dir, &rgui->browser->current_dir, sizeof(*(&rgui->browser->prev_dir)));
rgui->browser->prev_dir.ptr = rgui->browser->current_dir.ptr;
}
menu_stack_enum_array[stack_idx] = menu_type;
stack_idx++;
}
/*============================================================
EVENT CALLBACKS (AND RELATED)
============================================================ */
uint8_t first_setting = FIRST_SETTING;
uint8_t max_settings = 0;
uint8_t items_pages[SETTING_LAST_LAST] = {0};
static unsigned hist_opt_selected = 0;
static unsigned core_opt_selected = 0;
#include "rmenudisp.c"
static int select_file(void *data, uint64_t action)
{
rgui_handle_t *rgui = (rgui_handle_t*)data;
char path[PATH_MAX];
bool pop_menu_stack = false;
switch (action)
{
case RGUI_ACTION_OK:
if (filebrowser_is_current_entry_dir(rgui->browser))
{
if (!filebrowser_iterate(rgui->browser, RGUI_ACTION_OK))
{
RARCH_ERR("Failed to open directory.\n");
msg_queue_push(g_extern.msg_queue, "ERROR - Failed to open directory.", 1, 180);
}
}
else
{
strlcpy(path, rgui->browser->current_dir.path, sizeof(path));
switch(rgui->menu_type)
{
#ifdef HAVE_SHADER_MANAGER
case CONFIG_CHOICE:
menu_replace_config(path);
break;
case SHADER_CHOICE:
strlcpy(rgui->shader.pass[shader_choice_set_shader_slot].source.cg, path,
sizeof(rgui->shader.pass[shader_choice_set_shader_slot].source.cg));
break;
case CGP_CHOICE:
{
config_file_t *conf = NULL;
strlcpy(g_settings.video.shader_path, path, sizeof(g_settings.video.shader_path));
conf = config_file_new(path);
if (conf)
gfx_shader_read_conf_cgp(conf, &rgui->shader);
config_file_free(conf);
if (video_set_shader_func(RARCH_SHADER_CG, path))
g_settings.video.shader_enable = true;
else
{
RARCH_ERR("Setting CGP failed.\n");
g_settings.video.shader_enable = false;
}
}
break;
#endif
case BORDER_CHOICE:
if (menu_texture)
{
#ifdef _XBOX
if (menu_texture->vertex_buf)
{
menu_texture->vertex_buf->Release();
menu_texture->vertex_buf = NULL;
}
if (menu_texture->pixels)
{
menu_texture->pixels->Release();
menu_texture->pixels = NULL;
}
#else
free(menu_texture->pixels);
menu_texture->pixels = NULL;
#endif
menu_texture = (struct texture_image*)calloc(1, sizeof(*menu_texture));
}
texture_image_load(path, menu_texture);
strlcpy(g_extern.menu_texture_path, path, sizeof(g_extern.menu_texture_path));
if (driver.video_poke && driver.video_poke->set_texture_frame)
driver.video_poke->set_texture_frame(driver.video_data, menu_texture->pixels,
true, menu_texture->width, menu_texture->height, 1.0f);
break;
case LIBRETRO_CHOICE:
rarch_environment_cb(RETRO_ENVIRONMENT_SET_LIBRETRO_PATH, (void*)path);
g_extern.lifecycle_mode_state |= (1ULL << MODE_EXITSPAWN);
return -1;
case FILE_BROWSER_MENU:
strlcpy(g_extern.fullpath, path, sizeof(g_extern.fullpath));
g_extern.lifecycle_mode_state |= (1ULL << MODE_LOAD_GAME);
return -1;
}
pop_menu_stack = true;
}
break;
case RGUI_ACTION_CANCEL:
if (rgui->menu_type == LIBRETRO_CHOICE)
pop_menu_stack = true;
else
{
char tmp_str[PATH_MAX];
fill_pathname_parent_dir(tmp_str, rgui->browser->current_dir.directory_path, sizeof(tmp_str));
if (tmp_str[0] == '\0')
pop_menu_stack = true;
}
break;
case RGUI_ACTION_MAPPING_PREVIOUS:
if (rgui->menu_type == FILE_BROWSER_MENU)
{
const char * drive_map = menu_drive_mapping_previous();
if (drive_map != NULL)
filebrowser_set_root_and_ext(rgui->browser, rgui->browser->current_dir.extensions, drive_map);
}
break;
case RGUI_ACTION_MAPPING_NEXT:
if (rgui->menu_type == FILE_BROWSER_MENU)
{
const char * drive_map = menu_drive_mapping_next();
if (drive_map != NULL)
filebrowser_set_root_and_ext(rgui->browser, rgui->browser->current_dir.extensions, drive_map);
}
break;
}
if (pop_menu_stack)
menu_stack_pop(rgui->menu_type);
return 0;
}
static int select_directory(void *data, uint64_t action)
{
rgui_handle_t *rgui = (rgui_handle_t*)data;
char path[PATH_MAX];
(void)path;
bool ret = true;
bool is_dir = filebrowser_is_current_entry_dir(rgui->browser);
bool pop_menu_stack = false;
switch (action)
{
case RGUI_ACTION_OK:
#if 1
if (is_dir)
ret = filebrowser_iterate(rgui->browser, RGUI_ACTION_OK);
#else
/* TODO - extra conditional needed here to recognize if user pressed