Merge branch 'master' into send_debug

This commit is contained in:
Brad Parker 2019-03-07 19:23:41 -05:00
commit 9279d06f93
30 changed files with 635 additions and 203 deletions

View File

@ -39,7 +39,7 @@ RARCH_DEFINES += -DHAVE_GRIFFIN=1 -DRARCH_INTERNAL -DRARCH_CONSOLE -DHAVE_MENU -
LIBDIR =
LDFLAGS += -L$(PS2SDK)/ports/lib -L$(PS2DEV)/gsKit/lib -L$(PS2SDK)/ee/lib -L.
LIBS += -lretro_ps2 -lgskit -ldmakit -lgskit_toolkit -laudsrv -lpad -lmc -lhdd -lsdl -lfileXio -lpatches -lpoweroff
LIBS += -lretro_ps2 -lgskit -ldmakit -lgskit_toolkit -laudsrv -lmf -lpad -lmc -lhdd -lsdl -lfileXio -lpatches -lpoweroff
#IRX modules
# IRX modules - modules have to be in IRX_DIR

View File

@ -23,13 +23,12 @@
#include "../audio_driver.h"
#define AUDIO_BUFFER 64 * 1024
#define AUDIO_BUFFER 128 * 1024
#define AUDIO_CHANNELS 2
#define AUDIO_BITS 16
typedef struct ps2_audio
{
fifo_buffer_t* buffer;
bool nonblocking;
bool running;
@ -82,21 +81,15 @@ static void ps2_audio_free(void *data)
static ssize_t ps2_audio_write(void *data, const void *buf, size_t size)
{
int bytes_sent;
ps2_audio_t* ps2 = (ps2_audio_t*)data;
if (!ps2->running)
return -1;
if (ps2->nonblocking)
{
if (fifo_write_avail(ps2->buffer) < size)
return 0;
}
bytes_sent = audsrv_play_audio(buf, size);
audsrv_wait_audio(size);
audsrv_play_audio(buf, size);
return size;
return bytes_sent;
}
static bool ps2_audio_alive(void *data)

106
command.c Normal file → Executable file
View File

@ -277,66 +277,45 @@ bool command_set_shader(const char *arg)
#define SMY_CMD_STR "READ_CORE_RAM"
static bool command_read_ram(const char *arg)
{
#if defined(HAVE_NEW_CHEEVOS)
#if !defined(HAVE_NEW_CHEEVOS)
cheevos_var_t var;
#endif
unsigned i;
char *reply = NULL;
const uint8_t * data = NULL;
char *reply = NULL;
const uint8_t *data = NULL;
char *reply_at = NULL;
unsigned int nbytes = 0;
unsigned int alloc_size = 0;
unsigned int addr = -1;
unsigned int addr = -1;
if (sscanf(arg, "%x %d", &addr, &nbytes) != 2)
return true;
alloc_size = 40 + nbytes * 3; /* We alloc more than needed, saving 20 bytes is not really relevant */
reply = (char*) malloc(alloc_size);
reply[0] = '\0';
reply_at = reply + snprintf(reply, alloc_size - 1, SMY_CMD_STR " %x", addr);
#if defined(HAVE_NEW_CHEEVOS)
data = cheevos_patch_address(addr, cheevos_get_console());
if (data)
{
for (i = 0; i < nbytes; i++)
sprintf(reply_at+3*i, " %.2X", data[i]);
reply_at[3*nbytes] = '\n';
command_reply(reply, reply_at+3*nbytes+1 - reply);
}
else
{
strlcpy(reply_at, " -1\n", sizeof(reply)-strlen(reply));
command_reply(reply, reply_at+strlen(" -1\n") - reply);
}
free(reply);
#else
cheevos_var_t var;
unsigned i;
char reply[256] = {0};
const uint8_t * data = NULL;
char *reply_at = NULL;
reply[0] = '\0';
strlcpy(reply, "READ_CORE_RAM ", sizeof(reply));
reply_at = reply + strlen("READ_CORE_RAM ");
strlcpy(reply_at, arg, sizeof(reply)-strlen(reply));
var.value = strtoul(reply_at, (char**)&reply_at, 16);
var.value = addr;
cheevos_var_patch_addr(&var, cheevos_get_console());
data = cheevos_var_get_memory(&var);
#endif
if (data)
{
unsigned nbytes = strtol(reply_at, NULL, 10);
for (i = 0; i < nbytes; i++)
sprintf(reply_at+3*i, " %.2X", data[i]);
reply_at[3*nbytes] = '\n';
command_reply(reply, reply_at+3*nbytes+1 - reply);
snprintf(reply_at + 3 * i, 4, " %.2X", data[i]);
reply_at[3 * nbytes] = '\n';
command_reply(reply, reply_at + 3 * nbytes + 1 - reply);
}
else
{
strlcpy(reply_at, " -1\n", sizeof(reply)-strlen(reply));
command_reply(reply, reply_at+strlen(" -1\n") - reply);
strlcpy(reply_at, " -1\n", sizeof(reply) - strlen(reply));
command_reply(reply, reply_at + strlen(" -1\n") - reply);
}
#endif
free(reply);
return true;
}
#undef SMY_CMD_STR
@ -2412,44 +2391,25 @@ TODO: Add a setting for these tweaks */
break;
case CMD_EVENT_ADD_TO_FAVORITES:
{
/* TODO/FIXME - does path_get(RARCH_PATH_CORE) depend on the system info struct? Investigate */
global_t *global = global_get_ptr();
struct retro_system_info *system = runloop_get_libretro_system_info();
const char *label = NULL;
char core_path[PATH_MAX_LENGTH];
char core_name[PATH_MAX_LENGTH];
struct string_list *str_list = (struct string_list*)data;
core_path[0] = '\0';
core_name[0] = '\0';
if (system)
if (str_list)
{
if (!string_is_empty(path_get(RARCH_PATH_CORE)))
strlcpy(core_path, path_get(RARCH_PATH_CORE), sizeof(core_path));
if (!string_is_empty(system->library_name))
strlcpy(core_name, system->library_name, sizeof(core_name));
if (str_list->size >= 4)
{
/* Write playlist entry */
command_playlist_push_write(
g_defaults.content_favorites,
str_list->elems[0].data, /* content_path */
str_list->elems[1].data, /* content_label */
str_list->elems[2].data, /* core_path */
str_list->elems[3].data /* core_name */
);
runloop_msg_queue_push(msg_hash_to_str(MSG_ADDED_TO_FAVORITES), 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
}
}
if (string_is_empty(core_path))
strlcpy(core_path, file_path_str(FILE_PATH_DETECT), sizeof(core_path));
if (string_is_empty(core_name))
strlcpy(core_name, file_path_str(FILE_PATH_DETECT), sizeof(core_name));
if (!string_is_empty(global->name.label))
label = global->name.label;
command_playlist_push_write(
g_defaults.content_favorites,
(const char*)data,
label,
core_path,
core_name
);
runloop_msg_queue_push(msg_hash_to_str(MSG_ADDED_TO_FAVORITES), 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
break;
}
case CMD_EVENT_RESET_CORE_ASSOCIATION:
{

View File

@ -717,6 +717,9 @@ static const bool playlist_show_core_name = false;
static const bool playlist_show_sublabels = false;
/* Specifies which runtime record to use on playlist sublabels */
static unsigned playlist_sublabel_runtime_type = PLAYLIST_RUNTIME_PER_CORE;
/* Show Menu start-up screen on boot. */
static const bool default_menu_show_start_screen = true;
@ -794,6 +797,9 @@ static const bool desktop_menu_enable = true;
/* Keep track of how long each core+content has been running for over time */
static const bool content_runtime_log = false;
/* Keep track of how long each content has been running for over time (ignores core) */
static const bool content_runtime_log_aggregate = false;
#if defined(__QNX__) || defined(_XBOX1) || defined(_XBOX360) || defined(__CELLOS_LV2__) || (defined(__MACH__) && defined(IOS)) || defined(ANDROID) || defined(WIIU) || defined(HAVE_NEON) || defined(GEKKO) || defined(__ARM_NEON__)
static enum resampler_quality audio_resampler_quality_level = RESAMPLER_QUALITY_LOWER;
#elif defined(PSP) || defined(_3DS) || defined(VITA) || defined(PS2)

View File

@ -1578,7 +1578,8 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
#endif
SETTING_BOOL("playlist_use_old_format", &settings->bools.playlist_use_old_format, true, playlist_use_old_format, false);
SETTING_BOOL("content_runtime_log", &settings->bools.content_runtime_log, true, content_runtime_log, false);
SETTING_BOOL("content_runtime_log", &settings->bools.content_runtime_log, true, content_runtime_log, false);
SETTING_BOOL("content_runtime_log_aggregate", &settings->bools.content_runtime_log_aggregate, true, content_runtime_log_aggregate, false);
SETTING_BOOL("playlist_show_sublabels", &settings->bools.playlist_show_sublabels, true, playlist_show_sublabels, false);
SETTING_BOOL("playlist_show_core_name", &settings->bools.playlist_show_core_name, true, playlist_show_core_name, false);
SETTING_BOOL("playlist_sort_alphabetical", &settings->bools.playlist_sort_alphabetical, true, playlist_sort_alphabetical, false);
@ -1762,6 +1763,8 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
SETTING_UINT("libnx_overclock", &settings->uints.libnx_overclock, true, SWITCH_DEFAULT_CPU_PROFILE, false);
#endif
SETTING_UINT("playlist_sublabel_runtime_type", &settings->uints.playlist_sublabel_runtime_type, true, playlist_sublabel_runtime_type, false);
*size = count;
return tmp;

View File

@ -309,6 +309,7 @@ typedef struct settings
bool sustained_performance_mode;
bool playlist_use_old_format;
bool content_runtime_log;
bool content_runtime_log_aggregate;
bool playlist_show_core_name;
bool playlist_sort_alphabetical;
@ -438,6 +439,8 @@ typedef struct settings
unsigned menu_rgui_internal_upscale_level;
unsigned menu_ticker_type;
unsigned playlist_sublabel_runtime_type;
unsigned camera_width;
unsigned camera_height;

View File

@ -539,6 +539,7 @@ static core_info_t *core_info_find_internal(
const char *core)
{
size_t i;
const char *core_path_basename = path_basename(core);
for (i = 0; i < list->count; i++)
{
@ -546,7 +547,7 @@ static core_info_t *core_info_find_internal(
if (!info || !info->path)
continue;
if (string_is_equal(info->path, core))
if (string_is_equal(path_basename(info->path), core_path_basename))
return info;
}
@ -799,13 +800,16 @@ void core_info_list_get_supported_cores(core_info_list_t *core_info_list,
void core_info_get_name(const char *path, char *s, size_t len,
const char *path_info, const char *dir_cores,
const char *exts, bool dir_show_hidden_files)
const char *exts, bool dir_show_hidden_files,
bool get_display_name)
{
size_t i;
const char *path_basedir = !string_is_empty(path_info) ?
path_info : dir_cores;
struct string_list *contents = dir_list_new(
dir_cores, exts, false, dir_show_hidden_files, false, false);
const char *core_path_basename = path_basename(path);
if (!contents)
return;
@ -817,7 +821,7 @@ void core_info_get_name(const char *path, char *s, size_t len,
char *new_core_name = NULL;
const char *current_path = contents->elems[i].data;
if (!string_is_equal(current_path, path))
if (!string_is_equal(path_basename(current_path), core_path_basename))
continue;
info_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
@ -839,7 +843,7 @@ void core_info_get_name(const char *path, char *s, size_t len,
continue;
}
if (config_get_string(conf, "corename",
if (config_get_string(conf, get_display_name ? "display_name" : "corename",
&new_core_name))
{
strlcpy(s, new_core_name, len);

View File

@ -101,7 +101,8 @@ bool core_info_get_display_name(const char *path, char *s, size_t len);
void core_info_get_name(const char *path, char *s, size_t len,
const char *path_info, const char *dir_cores,
const char *exts, bool show_hidden_files);
const char *exts, bool show_hidden_files,
bool get_display_name);
core_info_t *core_info_get(core_info_list_t *list, size_t i);

View File

@ -1279,6 +1279,14 @@ bool rarch_environment_cb(unsigned cmd, void *data)
case RETRO_ENVIRONMENT_SHUTDOWN:
RARCH_LOG("Environ SHUTDOWN.\n");
/* This case occurs when a core (internally) requests
* a shutdown event. Must save runtime log file here,
* since normal command.c CMD_EVENT_CORE_DEINIT event
* will not occur until after the current content has
* been cleared (causing log to be skipped) */
rarch_ctl(RARCH_CTL_CONTENT_RUNTIME_LOG_DEINIT, NULL);
rarch_ctl(RARCH_CTL_SET_SHUTDOWN, NULL);
rarch_ctl(RARCH_CTL_SET_CORE_SHUTDOWN, NULL);
break;

View File

@ -241,21 +241,14 @@ static void frontend_ps2_init(void *data)
static void frontend_ps2_deinit(void *data)
{
(void)data;
#ifndef IS_SALAMANDER
#if defined(HAVE_FILE_LOGGER)
verbosity_disable();
#ifdef HAVE_FILE_LOGGER
command_event(CMD_EVENT_LOG_FILE_DEINIT, NULL);
#endif
#endif
padEnd();
audsrv_quit();
fileXioUmount("pfs0:");
fileXioExit();
SifExitRpc();
Exit(0);
}
static void frontend_ps2_exec(const char *path, bool should_load_game)

View File

@ -276,7 +276,11 @@ static bool ps2_gfx_frame(void *data, const void *frame,
bool sendPalette = false;
struct retro_hw_ps2_insets padding = empty_ps2_insets;
if (frame != RETRO_HW_FRAME_BUFFER_VALID){ /* Checking if the transfer is done in the core */
transfer_texture(ps2->coreTexture, frame, width, height, ps2->PSM, ps2->core_filter, 1);
/* calculate proper width based in the pitch */
int bytes_per_pixel = (ps2->PSM == GS_PSM_CT32) ? 4 : 2;
int real_width = pitch / bytes_per_pixel;
transfer_texture(ps2->coreTexture, frame, real_width, height, ps2->PSM, ps2->core_filter, 1);
padding.right = real_width - width;
} else {
sendPalette = ps2->iface.updatedPalette;
ps2->iface.updatedPalette = false;

View File

@ -43,8 +43,24 @@ static u32 gsKit_fontm_clut[16] = { 0x00000000, 0x11111111, 0x22222222, 0x333333
0x80888888, 0x80999999, 0x80AAAAAA, 0x80BBBBBB, \
0x80CCCCCC, 0x80DDDDDD, 0x80EEEEEE, 0x80FFFFFF };
static void ps2_prepare_font(GSGLOBAL *gsGlobal, GSFONTM *gsFontM)
static void deinit_texture(GSTEXTURE *texture)
{
free(texture->Mem);
free(texture->Clut);
texture->Mem = NULL;
texture->Clut = NULL;
}
static void deinit_gsfont(GSFONTM *gsFontM)
{
deinit_texture(gsFontM->Texture);
free(gsFontM->TexBase);
gsFontM->TexBase = NULL;
free(gsFontM);
}
static void ps2_prepare_font(GSGLOBAL *gsGlobal, GSFONTM *gsFontM)
{
if(gsKit_fontm_unpack(gsFontM) == 0) {
gsFontM->Texture->Width = FONTM_TEXTURE_WIDTH;
gsFontM->Texture->Height = FONTM_TEXTURE_HEIGHT;
@ -94,8 +110,9 @@ static void *ps2_font_init_font(void *gl_data, const char *font_path,
static void ps2_font_free_font(void *data, bool is_threaded)
{
ps2_font_info_t *ps2 = (ps2_font_info_t *)data;
free(ps2->gsFontM);
free(ps2);
deinit_gsfont(ps2->gsFontM);
ps2->ps2_video = NULL;
ps2 = NULL;
}
static void ps2_font_render_msg(

View File

@ -1789,11 +1789,15 @@ MSG_HASH(MENU_ENUM_LABEL_MENU_SOUND_BGM,
"menu_sound_bgm")
MSG_HASH(MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG,
"content_runtime_log")
MSG_HASH(MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG_AGGREGATE,
"content_runtime_log_aggregate")
MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_SHOW_CORE_NAME,
"playlist_show_core_name")
MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_SORT_ALPHABETICAL,
"playlist_sort_alphabetical")
MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_SHOW_SUBLABELS,
"playlist_show_sublabels")
MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_SUBLABEL_RUNTIME_TYPE,
"playlist_sublabel_runtime_type")
MSG_HASH(MENU_ENUM_LABEL_HELP_SEND_DEBUG_INFO,
"help_send_debug_info")

View File

@ -8312,11 +8312,19 @@ MSG_HASH(
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_CONTENT_RUNTIME_LOG,
"Save content runtime log"
"Save runtime log (per core)"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_CONTENT_RUNTIME_LOG,
"Keeps track of how long your content has been running over time."
"Keeps track of how long each item of content has run for, with records separated by core."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_CONTENT_RUNTIME_LOG_AGGREGATE,
"Save runtime log (aggregate)"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_CONTENT_RUNTIME_LOG_AGGREGATE,
"Keeps track of how long each item of content has run for, recorded as the aggregate total across all cores."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_PLAYLIST_SHOW_SUBLABELS,
@ -8324,7 +8332,7 @@ MSG_HASH(
)
MSG_HASH(
MENU_ENUM_SUBLABEL_PLAYLIST_SHOW_SUBLABELS,
"Shows additional information for each playlist entry, such as current core association and play time (if available). Has a variable performance impact."
"Shows additional information for each playlist entry, such as current core association and runtime (if available). Has a variable performance impact."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_CORE,
@ -8338,6 +8346,22 @@ MSG_HASH(
MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_LAST_PLAYED,
"Last Played:"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_RUNTIME_TYPE,
"Playlist sublabel runtime"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_PLAYLIST_SUBLABEL_RUNTIME_TYPE,
"Selects which type of runtime log record to display on playlist sublabels. (Note that the corresponding runtime log must be enabled via the 'Saving' options menu)"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_PLAYLIST_RUNTIME_PER_CORE,
"Per Core"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_PLAYLIST_RUNTIME_AGGREGATE,
"Aggregate"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_HELP_SEND_DEBUG_INFO,
"Send Debug Info"

View File

@ -222,8 +222,8 @@ int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, i
#elif defined(__CELLOS_LV2__) || defined(_MSC_VER) && _MSC_VER <= 1310
return fseek(stream->fp, (long)offset, whence);
#elif defined(PS2)
int64_t ret = fioLseek(fileno(stream->fp), (off_t)offset, whence);
/* fioLseek could return positive numbers */
int64_t ret = fileXioLseek(fileno(stream->fp), (off_t)offset, whence);
/* fileXioLseek could return positive numbers */
if (ret > 0) {
ret = 0;
}

View File

@ -2672,7 +2672,8 @@ static int action_ok_core_deferred_set(const char *new_core_path,
settings->paths.path_libretro_info,
settings->paths.directory_libretro,
ext_name,
settings->bools.show_hidden_files);
settings->bools.show_hidden_files,
true);
command_playlist_update_write(
NULL,
menu->scratchpad.unsigned_var,
@ -3809,35 +3810,200 @@ static int action_ok_reset_core_association(const char *path,
return 0;
}
/* This function is called when selecting 'add to favorites'
* while viewing the quick menu (i.e. content is running) */
static int action_ok_add_to_favorites(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx)
{
void *new_path = (void*)path_get(RARCH_PATH_CONTENT);
if (!command_event(CMD_EVENT_ADD_TO_FAVORITES, new_path))
return menu_cbs_exit();
return 0;
const char *content_path = path_get(RARCH_PATH_CONTENT);
int ret = 0;
/* Error checking
* > If content path is empty, cannot do anything... */
if (!string_is_empty(content_path))
{
global_t *global = global_get_ptr();
struct retro_system_info *system = runloop_get_libretro_system_info();
struct string_list *str_list = NULL;
union string_list_elem_attr attr;
char content_label[PATH_MAX_LENGTH];
char core_path[PATH_MAX_LENGTH];
char core_name[PATH_MAX_LENGTH];
content_label[0] = '\0';
core_path[0] = '\0';
core_name[0] = '\0';
/* Create string list container for playlist parameters */
attr.i = 0;
str_list = string_list_new();
if (!str_list)
return 0;
/* Determine playlist parameters */
/* > content_label */
if (global)
if (!string_is_empty(global->name.label))
strlcpy(content_label, global->name.label, sizeof(content_label));
if (string_is_empty(content_label)) /* Label is empty - use file name instead */
fill_short_pathname_representation(content_label, content_path, sizeof(content_label));
/* > core_path + core_name */
if (system)
{
if (!string_is_empty(path_get(RARCH_PATH_CORE)))
{
core_info_ctx_find_t core_info;
/* >> core_path */
strlcpy(core_path, path_get(RARCH_PATH_CORE), sizeof(core_path));
/* >> core_name
* (always use display name, if available) */
core_info.inf = NULL;
core_info.path = core_path;
if (core_info_find(&core_info, core_path))
if (!string_is_empty(core_info.inf->display_name))
strlcpy(core_name, core_info.inf->display_name, sizeof(core_name));
}
/* >> core_name (continued) */
if (string_is_empty(core_name) && !string_is_empty(system->library_name))
strlcpy(core_name, system->library_name, sizeof(core_name));
}
if (string_is_empty(core_path) || string_is_empty(core_name))
{
strlcpy(core_path, file_path_str(FILE_PATH_DETECT), sizeof(core_path));
strlcpy(core_name, file_path_str(FILE_PATH_DETECT), sizeof(core_name));
}
/* Copy playlist parameters into string list
* [0]: content_path
* [1]: content_label
* [2]: core_path
* [3]: core_name */
string_list_append(str_list, content_path, attr);
string_list_append(str_list, content_label, attr);
string_list_append(str_list, core_path, attr);
string_list_append(str_list, core_name, attr);
/* Trigger 'ADD_TO_FAVORITES' event */
if (!command_event(CMD_EVENT_ADD_TO_FAVORITES, (void*)str_list))
ret = menu_cbs_exit();
/* Clean up */
string_list_free(str_list);
str_list = NULL;
}
return ret;
}
/* This function is called when selecting 'add to favorites'
* while viewing a playlist entry */
static int action_ok_add_to_favorites_playlist(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx)
{
const char *tmp_path = NULL;
menu_handle_t *menu = NULL;
playlist_t *tmp_playlist = playlist_get_cached();
const char *content_path = NULL;
const char *content_label = NULL;
const char *core_path = NULL;
const char *core_name = NULL;
menu_handle_t *menu = NULL;
playlist_t *tmp_playlist = playlist_get_cached();
int ret = 0;
if (!tmp_playlist)
return 0;
if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu))
return menu_cbs_exit();
playlist_get_index(tmp_playlist,
menu->rpl_entry_selection_ptr, &tmp_path,
NULL, NULL, NULL, NULL, NULL);
/* Read current playlist parameters */
playlist_get_index(tmp_playlist, menu->rpl_entry_selection_ptr,
&content_path, &content_label, &core_path, &core_name,
NULL, NULL);
if (!command_event(CMD_EVENT_ADD_TO_FAVORITES, (void*)tmp_path))
return menu_cbs_exit();
return 0;
/* Error checking
* > If content path is empty, cannot do anything... */
if (!string_is_empty(content_path))
{
struct string_list *str_list = NULL;
union string_list_elem_attr attr;
char core_display_name[PATH_MAX_LENGTH];
core_display_name[0] = '\0';
/* Create string list container for playlist parameters */
attr.i = 0;
str_list = string_list_new();
if (!str_list)
return 0;
/* Copy playlist parameters into string list
* [0]: content_path
* [1]: content_label
* [2]: core_path
* [3]: core_name */
/* > content_path */
string_list_append(str_list, content_path, attr);
/* > content_label */
if (!string_is_empty(content_label))
{
string_list_append(str_list, content_label, attr);
}
else
{
/* Label is empty - use file name instead */
char fallback_content_label[PATH_MAX_LENGTH];
fallback_content_label[0] = '\0';
fill_short_pathname_representation(fallback_content_label, content_path, sizeof(fallback_content_label));
string_list_append(str_list, fallback_content_label, attr);
}
/* > core_path + core_name */
if (!string_is_empty(core_path) && !string_is_empty(core_name))
{
core_info_ctx_find_t core_info;
/* >> core_path */
string_list_append(str_list, core_path, attr);
/* >> core_name
* (always use display name, if available) */
core_info.inf = NULL;
core_info.path = core_path;
if (core_info_find(&core_info, core_path))
if (!string_is_empty(core_info.inf->display_name))
strlcpy(core_display_name, core_info.inf->display_name, sizeof(core_display_name));
if (!string_is_empty(core_display_name))
string_list_append(str_list, core_display_name, attr);
else
string_list_append(str_list, core_name, attr);
}
else
{
string_list_append(str_list, file_path_str(FILE_PATH_DETECT), attr);
string_list_append(str_list, file_path_str(FILE_PATH_DETECT), attr);
}
/* Trigger 'ADD_TO_FAVORITES' event */
if (!command_event(CMD_EVENT_ADD_TO_FAVORITES, (void*)str_list))
ret = menu_cbs_exit();
/* Clean up */
string_list_free(str_list);
str_list = NULL;
}
return ret;
}
static int action_ok_delete_entry(const char *path,

View File

@ -522,6 +522,8 @@ default_sublabel_macro(action_bind_sublabel_rgui_menu_color_theme,
default_sublabel_macro(action_bind_sublabel_rgui_menu_theme_preset, MENU_ENUM_SUBLABEL_RGUI_MENU_THEME_PRESET)
default_sublabel_macro(action_bind_sublabel_menu_rgui_thumbnail_downscaler, MENU_ENUM_SUBLABEL_MENU_RGUI_THUMBNAIL_DOWNSCALER)
default_sublabel_macro(action_bind_sublabel_content_runtime_log, MENU_ENUM_SUBLABEL_CONTENT_RUNTIME_LOG)
default_sublabel_macro(action_bind_sublabel_content_runtime_log_aggregate, MENU_ENUM_SUBLABEL_CONTENT_RUNTIME_LOG_AGGREGATE)
default_sublabel_macro(action_bind_sublabel_playlist_sublabel_runtime_type, MENU_ENUM_SUBLABEL_PLAYLIST_SUBLABEL_RUNTIME_TYPE)
default_sublabel_macro(action_bind_sublabel_menu_rgui_internal_upscale_level, MENU_ENUM_SUBLABEL_MENU_RGUI_INTERNAL_UPSCALE_LEVEL)
default_sublabel_macro(action_bind_sublabel_menu_ticker_type, MENU_ENUM_SUBLABEL_MENU_TICKER_TYPE)
default_sublabel_macro(action_bind_sublabel_menu_ticker_speed, MENU_ENUM_SUBLABEL_MENU_TICKER_SPEED)
@ -856,9 +858,12 @@ static int action_bind_sublabel_playlist_entry(
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_CORE),
core_name);
/* Get runtime info *if* runtime logging is enabled
/* Get runtime info *if* required runtime log is enabled
* *and* this is a valid playlist type */
if (!settings->bools.content_runtime_log)
if (((settings->uints.playlist_sublabel_runtime_type == PLAYLIST_RUNTIME_PER_CORE) &&
!settings->bools.content_runtime_log) ||
((settings->uints.playlist_sublabel_runtime_type == PLAYLIST_RUNTIME_AGGREGATE) &&
!settings->bools.content_runtime_log_aggregate))
return 0;
/* Note: This looks heavy, but each string_is_equal() call will
@ -2377,6 +2382,12 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_content_runtime_log);
break;
case MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG_AGGREGATE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_content_runtime_log_aggregate);
break;
case MENU_ENUM_LABEL_PLAYLIST_SUBLABEL_RUNTIME_TYPE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_playlist_sublabel_runtime_type);
break;
case MENU_ENUM_LABEL_MENU_RGUI_INTERNAL_UPSCALE_LEVEL:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_rgui_internal_upscale_level);
break;

View File

@ -303,6 +303,13 @@ enum menu_input_ctl_state
MENU_INPUT_CTL_DEINIT
};
enum playlist_sublabel_runtime
{
PLAYLIST_RUNTIME_PER_CORE = 0,
PLAYLIST_RUNTIME_AGGREGATE,
PLAYLIST_RUNTIME_LAST
};
typedef uintptr_t menu_texture_item;
typedef struct menu_display_ctx_clearcolor

View File

@ -1302,7 +1302,10 @@ static int menu_displaylist_parse_playlist(menu_displaylist_info_t *info,
goto error;
/* Check whether runtime logging info should be parsed */
if (settings->bools.content_runtime_log)
if (((settings->uints.playlist_sublabel_runtime_type == PLAYLIST_RUNTIME_PER_CORE) &&
settings->bools.content_runtime_log) ||
((settings->uints.playlist_sublabel_runtime_type == PLAYLIST_RUNTIME_AGGREGATE) &&
settings->bools.content_runtime_log_aggregate))
{
/* Runtime logging is valid for every type of playlist *apart from*
* images/music/video history */
@ -1350,7 +1353,8 @@ static int menu_displaylist_parse_playlist(menu_displaylist_info_t *info,
if (get_runtime)
{
runtime_log_t *runtime_log = NULL;
runtime_log = runtime_log_init(path, core_path);
runtime_log = runtime_log_init(path, core_path,
settings->uints.playlist_sublabel_runtime_type == PLAYLIST_RUNTIME_PER_CORE);
if (runtime_log)
{
@ -2954,15 +2958,6 @@ static int menu_displaylist_parse_horizontal_content_actions(
if (settings->bools.quick_menu_show_add_to_favorites)
{
global_t *global = global_get_ptr();
/* Have to update global->name.label here, otherwise
* the 'Add to Favorites' option will produce nonsensical
* playlist entries... */
if (global)
if (!string_is_empty(label))
strlcpy(global->name.label, label, sizeof(global->name.label));
menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ADD_TO_FAVORITES_PLAYLIST),
msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_FAVORITES_PLAYLIST),
@ -5355,6 +5350,9 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist
ret = menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_PLAYLIST_SHOW_SUBLABELS,
PARSE_ONLY_BOOL, false);
ret = menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_PLAYLIST_SUBLABEL_RUNTIME_TYPE,
PARSE_ONLY_UINT, false);
ret = menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_PLAYLIST_SHOW_CORE_NAME,
PARSE_ONLY_BOOL, false);
@ -5479,6 +5477,9 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist
menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG,
PARSE_ONLY_BOOL, false);
menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG_AGGREGATE,
PARSE_ONLY_BOOL, false);
info->need_refresh = true;
info->need_push = true;

View File

@ -545,8 +545,7 @@ bool menu_display_libretro(bool is_idle,
command_event(CMD_EVENT_DISCORD_UPDATE, &userdata);
#endif
return true; /* Maybe return false here
for indication of idleness? */
return false; /* Return false here for indication of idleness */
}
return video_driver_cached_frame();
}

View File

@ -337,16 +337,16 @@ static void setting_get_string_representation_video_stream_quality(
/* TODO/FIXME - localize this */
switch (*setting->value.target.unsigned_integer)
{
case 8:
case RECORD_CONFIG_TYPE_STREAMING_CUSTOM:
strlcpy(s, "Custom", len);
break;
case 9:
case RECORD_CONFIG_TYPE_STREAMING_LOW_QUALITY:
strlcpy(s, "Low", len);
break;
case 10:
case RECORD_CONFIG_TYPE_STREAMING_MED_QUALITY:
strlcpy(s, "Medium", len);
break;
case 11:
case RECORD_CONFIG_TYPE_STREAMING_HIGH_QUALITY:
strlcpy(s, "High", len);
break;
}
@ -361,28 +361,28 @@ static void setting_get_string_representation_video_record_quality(rarch_setting
/* TODO/FIXME - localize this */
switch (*setting->value.target.unsigned_integer)
{
case 0:
case RECORD_CONFIG_TYPE_RECORDING_CUSTOM:
strlcpy(s, "Custom", len);
break;
case 1:
case RECORD_CONFIG_TYPE_RECORDING_LOW_QUALITY:
strlcpy(s, "Low", len);
break;
case 2:
case RECORD_CONFIG_TYPE_RECORDING_MED_QUALITY:
strlcpy(s, "Medium", len);
break;
case 3:
case RECORD_CONFIG_TYPE_RECORDING_HIGH_QUALITY:
strlcpy(s, "High", len);
break;
case 4:
case RECORD_CONFIG_TYPE_RECORDING_LOSSLESS_QUALITY:
strlcpy(s, "Lossless", len);
break;
case 5:
case RECORD_CONFIG_TYPE_RECORDING_WEBM_FAST:
strlcpy(s, "WebM Fast", len);
break;
case 6:
case RECORD_CONFIG_TYPE_RECORDING_WEBM_HIGH_QUALITY:
strlcpy(s, "WebM High Quality", len);
break;
case 7:
case RECORD_CONFIG_TYPE_RECORDING_GIF:
strlcpy(s, "GIF", len);
break;
}
@ -1298,6 +1298,30 @@ static void setting_get_string_representation_crt_switch_resolution_super(
snprintf(s, len, "%d", *setting->value.target.unsigned_integer);
}
static void setting_get_string_representation_uint_playlist_sublabel_runtime_type(
rarch_setting_t *setting,
char *s, size_t len)
{
if (!setting)
return;
switch (*setting->value.target.unsigned_integer)
{
case PLAYLIST_RUNTIME_PER_CORE:
strlcpy(s,
msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_PLAYLIST_RUNTIME_PER_CORE),
len);
break;
case PLAYLIST_RUNTIME_AGGREGATE:
strlcpy(s,
msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_PLAYLIST_RUNTIME_AGGREGATE),
len);
break;
}
}
static int setting_action_left_analog_dpad_mode(rarch_setting_t *setting, bool wraparound)
{
unsigned port = 0;
@ -4967,6 +4991,21 @@ static bool setting_append_list(
general_read_handler,
SD_FLAG_NONE);
CONFIG_BOOL(
list, list_info,
&settings->bools.content_runtime_log_aggregate,
MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG_AGGREGATE,
MENU_ENUM_LABEL_VALUE_CONTENT_RUNTIME_LOG_AGGREGATE,
content_runtime_log_aggregate,
MENU_ENUM_LABEL_VALUE_OFF,
MENU_ENUM_LABEL_VALUE_ON,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler,
SD_FLAG_NONE);
END_SUB_GROUP(list, list_info, parent_group);
END_GROUP(list, list_info, parent_group);
}
@ -7295,7 +7334,7 @@ static bool setting_append_list(
(*list)[list_info->index - 1].offset_by = 1;
menu_settings_list_current_add_range(list, list_info, 1, 65536, 1, true, true);
CONFIG_UINT(
CONFIG_UINT(
list, list_info,
&settings->uints.video_stream_quality,
MENU_ENUM_LABEL_VIDEO_STREAM_QUALITY,
@ -9884,6 +9923,22 @@ static bool setting_append_list(
SD_FLAG_NONE
);
CONFIG_UINT(
list, list_info,
&settings->uints.playlist_sublabel_runtime_type,
MENU_ENUM_LABEL_PLAYLIST_SUBLABEL_RUNTIME_TYPE,
MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_RUNTIME_TYPE,
playlist_sublabel_runtime_type,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].get_string_representation =
&setting_get_string_representation_uint_playlist_sublabel_runtime_type;
menu_settings_list_current_add_range(list, list_info, 0, PLAYLIST_RUNTIME_LAST-1, 1, true, true);
CONFIG_BOOL(
list, list_info,
&settings->bools.playlist_show_core_name,

View File

@ -2276,15 +2276,20 @@ enum msg_hash_enums
MENU_LABEL(MENU_SOUND_BGM),
MENU_ENUM_LABEL_VALUE_VIDEO_DRIVER_FALLBACK,
MENU_LABEL(CONTENT_RUNTIME_LOG),
MENU_LABEL(CONTENT_RUNTIME_LOG_AGGREGATE),
MENU_LABEL(PLAYLIST_SHOW_CORE_NAME),
MENU_LABEL(PLAYLIST_SORT_ALPHABETICAL),
MENU_LABEL(PLAYLIST_SHOW_SUBLABELS),
MENU_LABEL(PLAYLIST_SUBLABEL_RUNTIME_TYPE),
MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_CORE,
MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_RUNTIME,
MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_LAST_PLAYED,
MENU_ENUM_LABEL_VALUE_PLAYLIST_RUNTIME_PER_CORE,
MENU_ENUM_LABEL_VALUE_PLAYLIST_RUNTIME_AGGREGATE,
MENU_LABEL(HELP_SEND_DEBUG_INFO),
MENU_ENUM_LABEL_VALUE_HELP_SEND_DEBUG_INFO_DESC,

View File

@ -1567,13 +1567,76 @@ playlist_t *playlist_init(const char *path, size_t size)
static int playlist_qsort_func(const struct playlist_entry *a,
const struct playlist_entry *b)
{
const char *a_label = a ? a->label : NULL;
const char *b_label = b ? b->label : NULL;
char *a_str = NULL;
char *b_str = NULL;
char *a_fallback_label = NULL;
char *b_fallback_label = NULL;
int ret = 0;
if (!a_label || !b_label)
return 0;
if (!a || !b)
goto end;
return strcasecmp(a_label, b_label);
a_str = a->label;
b_str = b->label;
/* It is quite possible for playlist labels
* to be blank. If that is the case, have to use
* filename as a fallback (this is slow, but we
* have no other option...) */
if (string_is_empty(a_str))
{
if (string_is_empty(a->path))
goto end;
a_fallback_label = (char*)calloc(PATH_MAX_LENGTH, sizeof(char));
if (!a_fallback_label)
goto end;
fill_short_pathname_representation(a_fallback_label, a->path, PATH_MAX_LENGTH * sizeof(char));
if (string_is_empty(a_fallback_label))
goto end;
a_str = a_fallback_label;
}
if (string_is_empty(b_str))
{
if (string_is_empty(b->path))
goto end;
b_fallback_label = (char*)calloc(PATH_MAX_LENGTH, sizeof(char));
if (!b_fallback_label)
goto end;
fill_short_pathname_representation(b_fallback_label, b->path, PATH_MAX_LENGTH * sizeof(char));
if (string_is_empty(b_fallback_label))
goto end;
b_str = b_fallback_label;
}
ret = strcasecmp(a_str, b_str);
end:
a_str = NULL;
b_str = NULL;
if (a_fallback_label)
{
free(a_fallback_label);
a_fallback_label = NULL;
}
if (b_fallback_label)
{
free(b_fallback_label);
b_fallback_label = NULL;
}
return ret;
}
void playlist_qsort(playlist_t *playlist)

View File

@ -158,7 +158,7 @@ bool waitUntilDeviceIsReady(enum BootDeviceIDs device_id)
while(openFile < 0 && retries > 0)
{
openFile = fioDopen(rootDevice);
openFile = fileXioDopen(rootDevice);
/* Wait untill the device is ready */
nopdelay();
nopdelay();
@ -172,7 +172,7 @@ bool waitUntilDeviceIsReady(enum BootDeviceIDs device_id)
retries--;
};
fioDclose(openFile);
fileXioDclose(openFile);
return openFile >= 0;
}

View File

@ -571,7 +571,7 @@ static bool ffmpeg_init_config_common(struct ff_config_param *params, unsigned p
params->out_pix_fmt = PIX_FMT_YUV420P;
strlcpy(params->vcodec, "libx264", sizeof(params->vcodec));
strlcpy(params->acodec, "libmp3lame", sizeof(params->acodec));
strlcpy(params->acodec, "aac", sizeof(params->acodec));
av_dict_set(&params->video_opts, "preset", "ultrafast", 0);
av_dict_set(&params->video_opts, "tune", "animation", 0);
@ -587,7 +587,7 @@ static bool ffmpeg_init_config_common(struct ff_config_param *params, unsigned p
params->out_pix_fmt = PIX_FMT_YUV420P;
strlcpy(params->vcodec, "libx264", sizeof(params->vcodec));
strlcpy(params->acodec, "libmp3lame", sizeof(params->acodec));
strlcpy(params->acodec, "aac", sizeof(params->acodec));
av_dict_set(&params->video_opts, "preset", "superfast", 0);
av_dict_set(&params->video_opts, "tune", "animation", 0);
@ -603,7 +603,7 @@ static bool ffmpeg_init_config_common(struct ff_config_param *params, unsigned p
params->out_pix_fmt = PIX_FMT_YUV444P;
strlcpy(params->vcodec, "libx264", sizeof(params->vcodec));
strlcpy(params->acodec, "libmp3lame", sizeof(params->acodec));
strlcpy(params->acodec, "aac", sizeof(params->acodec));
av_dict_set(&params->video_opts, "preset", "superfast", 0);
av_dict_set(&params->video_opts, "tune", "animation", 0);
@ -663,7 +663,7 @@ static bool ffmpeg_init_config_common(struct ff_config_param *params, unsigned p
strlcpy(params->vcodec, "gif", sizeof(params->vcodec));
strlcpy(params->acodec, "", sizeof(params->acodec));
av_dict_set(&params->video_opts, "framerate", "50", 0);
av_dict_set(&params->video_opts, "framerate", "30", 0);
av_dict_set(&params->audio_opts, "audio_global_quality", "0", 0);
break;
case RECORD_CONFIG_TYPE_STREAMING_NETPLAY:
@ -694,7 +694,7 @@ static bool ffmpeg_init_config_common(struct ff_config_param *params, unsigned p
params->scale_factor = 1;
strlcpy(params->format, "matroska", sizeof(params->format));
}
else if (preset >= RECORD_CONFIG_TYPE_RECORDING_WEBM_FAST && settings->uints.video_record_quality < RECORD_CONFIG_TYPE_RECORDING_GIF)
else if (preset >= RECORD_CONFIG_TYPE_RECORDING_WEBM_FAST && preset < RECORD_CONFIG_TYPE_RECORDING_GIF)
{
if (!settings->bools.video_gpu_record)
params->scale_factor = settings->uints.video_record_scale_factor > 0 ?
@ -705,11 +705,7 @@ static bool ffmpeg_init_config_common(struct ff_config_param *params, unsigned p
}
else if (preset <= RECORD_CONFIG_TYPE_STREAMING_LOW_QUALITY)
{
if (!settings->bools.video_gpu_record)
params->scale_factor = settings->uints.video_record_scale_factor > 0 ?
settings->uints.video_record_scale_factor : 1;
else
params->scale_factor = 1;
params->scale_factor = 1;
strlcpy(params->format, "gif", sizeof(params->format));
}
else if (preset <= RECORD_CONFIG_TYPE_STREAMING_HIGH_QUALITY)

View File

@ -286,8 +286,12 @@ static unsigned fastforward_after_frames = 0;
static retro_usec_t runloop_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_time_t libretro_core_runtime_last = 0;
static retro_time_t libretro_core_runtime_usec = 0;
static char runtime_content_path[PATH_MAX_LENGTH] = {0};
static char runtime_core_path[PATH_MAX_LENGTH] = {0};
extern bool input_driver_flushing_input;
static char launch_arguments[4096];
@ -816,10 +820,63 @@ bool driver_ctl(enum driver_ctl_state state, void *data)
void rarch_core_runtime_tick(void)
{
retro_time_t frame_time;
struct retro_system_av_info *av_info = video_viewport_get_system_av_info();
if (av_info && av_info->timing.fps)
libretro_core_runtime_usec += (1.0 / av_info->timing.fps) * 1000 * 1000;
{
frame_time = (1.0 / av_info->timing.fps) * 1000000;
/* Account for slow motion */
if (runloop_slowmotion)
{
settings_t *settings = config_get_ptr();
if (settings)
frame_time = (retro_time_t)((double)frame_time * settings->floats.slowmotion_ratio);
}
/* Account for fast forward */
else if (runloop_fastmotion)
{
/* Doing it this way means we miss the first frame after
* turning fast forward on, but it saves the overhead of
* having to do:
* retro_time_t current_usec = cpu_features_get_time_usec();
* libretro_core_runtime_last = current_usec;
* every frame when fast forward is off. */
retro_time_t current_usec = cpu_features_get_time_usec();
if (current_usec - libretro_core_runtime_last < frame_time)
{
frame_time = current_usec - libretro_core_runtime_last;
}
libretro_core_runtime_last = current_usec;
}
libretro_core_runtime_usec += frame_time;
}
}
static void update_runtime_log(bool log_per_core)
{
runtime_log_t *runtime_log = NULL;
/* Initialise runtime log file */
runtime_log = runtime_log_init(runtime_content_path, runtime_core_path, log_per_core);
if (runtime_log)
{
/* Add additional runtime */
runtime_log_add_runtime_usec(runtime_log, libretro_core_runtime_usec);
/* Update 'last played' entry */
runtime_log_set_last_played_now(runtime_log);
/* Save runtime log file */
runtime_log_save(runtime_log);
/* Clean up */
free(runtime_log);
}
}
#ifdef HAVE_THREADS
@ -2391,8 +2448,35 @@ bool rarch_ctl(enum rarch_ctl_state state, void *data)
}
break;
case RARCH_CTL_CONTENT_RUNTIME_LOG_INIT:
{
const char *content_path = path_get(RARCH_PATH_CONTENT);
const char *core_path = path_get(RARCH_PATH_CORE);
libretro_core_runtime_last = cpu_features_get_time_usec();
libretro_core_runtime_usec = 0;
/* Have to cache content and core path here, otherwise
* logging fails if new content is loaded without
* closing existing content
* i.e. RARCH_PATH_CONTENT and RARCH_PATH_CORE get
* updated when the new content is loaded, which
* happens *before* RARCH_CTL_CONTENT_RUNTIME_LOG_DEINIT
* -> using RARCH_PATH_CONTENT and RARCH_PATH_CORE
* directly in RARCH_CTL_CONTENT_RUNTIME_LOG_DEINIT
* can therefore lead to the runtime of the currently
* loaded content getting written to the *new*
* content's log file... */
memset(runtime_content_path, 0, sizeof(runtime_content_path));
memset(runtime_core_path, 0, sizeof(runtime_core_path));
if (!string_is_empty(content_path))
strlcpy(runtime_content_path, content_path, sizeof(runtime_content_path));
if (!string_is_empty(core_path))
strlcpy(runtime_core_path, core_path, sizeof(runtime_core_path));
break;
}
case RARCH_CTL_CONTENT_RUNTIME_LOG_DEINIT:
{
settings_t *settings = config_get_ptr();
@ -2411,30 +2495,24 @@ bool rarch_ctl(enum rarch_ctl_state state, void *data)
n = 0; /* Just silence any potential gcc warnings... */
RARCH_LOG("%s\n",log);
/* Only write to file if logging is enabled *and* content has run
* for a non-zero length of time */
if (settings->bools.content_runtime_log && libretro_core_runtime_usec > 0)
/* Only write to file if content has run for a non-zero length of time */
if (libretro_core_runtime_usec > 0)
{
runtime_log_t *runtime_log = NULL;
/* Per core logging */
if (settings->bools.content_runtime_log)
update_runtime_log(true);
/* Initialise runtime log file */
runtime_log = runtime_log_init(path_get(RARCH_PATH_CONTENT), path_get(RARCH_PATH_CORE));
if (runtime_log)
{
/* Add additional runtime */
runtime_log_add_runtime_usec(runtime_log, libretro_core_runtime_usec);
/* Update 'last played' entry */
runtime_log_set_last_played_now(runtime_log);
/* Save runtime log file */
runtime_log_save(runtime_log);
/* Clean up */
free(runtime_log);
}
/* Aggregate logging */
if (settings->bools.content_runtime_log_aggregate)
update_runtime_log(false);
}
/* Reset runtime + content/core paths, to prevent any
* possibility of duplicate logging */
libretro_core_runtime_usec = 0;
memset(runtime_content_path, 0, sizeof(runtime_content_path));
memset(runtime_core_path, 0, sizeof(runtime_core_path));
break;
}
case RARCH_CTL_GET_PERFCNT:
@ -4335,16 +4413,18 @@ int runloop_iterate(unsigned *sleep_ms)
else
{
core_run();
rarch_core_runtime_tick();
}
}
#else
{
core_run();
rarch_core_runtime_tick();
}
#endif
/* Increment runtime tick counter after each call to
* core_run() or run_ahead() */
rarch_core_runtime_tick();
#ifdef HAVE_CHEEVOS
if (runloop_check_cheevos())
cheevos_test();

View File

@ -268,11 +268,12 @@ end:
/* Initialise runtime log, loading current parameters
* if log file exists. Returned object must be free()'d.
* Returns NULL if content_path and/or core_path are invalid */
runtime_log_t *runtime_log_init(const char *content_path, const char *core_path)
runtime_log_t *runtime_log_init(const char *content_path, const char *core_path, bool log_per_core)
{
settings_t *settings = config_get_ptr();
core_info_list_t *core_info = NULL;
runtime_log_t *runtime_log = NULL;
const char *core_path_basename = path_basename(core_path);
char content_name[PATH_MAX_LENGTH];
char core_name[PATH_MAX_LENGTH];
@ -298,13 +299,17 @@ runtime_log_t *runtime_log_init(const char *content_path, const char *core_path)
return NULL;
}
if (string_is_empty(content_path) || string_is_empty(core_path))
if (string_is_empty(content_path) || string_is_empty(core_path_basename))
return NULL;
if (string_is_equal(core_path, "builtin") || string_is_equal(core_path, file_path_str(FILE_PATH_DETECT)))
return NULL;
/* Get core name */
/* Get core name
* Note: An annoyance - this is required even when
* we are performing aggregate (not per core) logging,
* since content name is sometimes dependent upon core
* (e.g. see TyrQuake below) */
core_info_get_list(&core_info);
if (!core_info)
@ -312,7 +317,7 @@ runtime_log_t *runtime_log_init(const char *content_path, const char *core_path)
for (i = 0; i < core_info->count; i++)
{
if (string_is_equal(core_info->list[i].path, core_path))
if (string_is_equal(path_basename(core_info->list[i].path), core_path_basename))
{
strlcpy(core_name, core_info->list[i].core_name, sizeof(core_name));
break;
@ -329,11 +334,18 @@ runtime_log_t *runtime_log_init(const char *content_path, const char *core_path)
"logs",
sizeof(tmp_buf));
fill_pathname_join(
log_file_dir,
tmp_buf,
core_name,
sizeof(log_file_dir));
if (log_per_core)
{
fill_pathname_join(
log_file_dir,
tmp_buf,
core_name,
sizeof(log_file_dir));
}
else
{
strlcpy(log_file_dir, tmp_buf, sizeof(log_file_dir));
}
if (string_is_empty(log_file_dir))
return NULL;
@ -650,6 +662,8 @@ void runtime_log_save(runtime_log_t *runtime_log)
if (!runtime_log)
return;
RARCH_LOG("Saving runtime log file: %s\n", runtime_log->path);
/* Attempt to open log file */
file = filestream_open(runtime_log->path, RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE);

View File

@ -60,7 +60,7 @@ typedef struct
/* Initialise runtime log, loading current parameters
* if log file exists. Returned object must be free()'d.
* Returns NULL if content_path and/or core_path are invalid */
runtime_log_t *runtime_log_init(const char *content_path, const char *core_path);
runtime_log_t *runtime_log_init(const char *content_path, const char *core_path, bool log_per_core);
/* Setters */

View File

@ -1041,9 +1041,24 @@ static bool task_load_content(content_ctx_info_t *content_info,
#endif
break;
default:
{
core_info_t *core_info = NULL;
/* Set core path */
core_path = path_get(RARCH_PATH_CORE);
core_name = info->library_name;
/* Set core display name
* (As far as I can tell, core_info_get_current_core()
* should always provide a valid pointer here...) */
core_info_get_current_core(&core_info);
if (core_info)
core_name = core_info->display_name;
if (string_is_empty(core_name))
core_name = info->library_name;
break;
}
}
if (launched_from_cli)

View File

@ -1748,7 +1748,7 @@ QHash<QString, QString> MainWindow::getFileContentHash(const QModelIndex &index)
QFileInfo fileInfo = m_fileModel->fileInfo(index);
QHash<QString, QString> hash;
hash["path"] = m_fileModel->filePath(index);;
hash["path"] = QDir::toNativeSeparators(m_fileModel->filePath(index));
hash["label"] = hash["path"];
hash["label_noext"] = fileInfo.completeBaseName();
hash["db_name"] = fileInfo.dir().dirName();