2016-01-24 00:40:34 +01:00
/* RetroArch - A frontend for libretro.
2017-01-22 13:40:32 +01:00
* Copyright ( C ) 2011 - 2017 - Daniel De Matteis
* Copyright ( C ) 2016 - 2017 - Brad Parker
2016-01-24 00:40:34 +01:00
*
* 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 < http : //www.gnu.org/licenses/>.
*/
2016-05-17 14:31:33 +02:00
/* TODO/FIXME - turn this into actual task */
2016-05-16 16:42:33 +02:00
# include <stdio.h>
# include <stdint.h>
2016-01-24 00:40:34 +01:00
# include <stdlib.h>
2016-05-16 16:42:33 +02:00
# include <sys/types.h>
# include <string.h>
# include <time.h>
# include <errno.h>
2016-01-24 00:40:34 +01:00
2016-05-16 15:09:04 +02:00
# include <file/file_path.h>
2016-05-17 07:36:18 +02:00
# include <string/stdstring.h>
2016-05-16 15:09:04 +02:00
2016-05-16 16:42:33 +02:00
# ifdef _WIN32
# ifdef _XBOX
# include <xtl.h>
# define setmode _setmode
# define INVALID_FILE_ATTRIBUTES -1
# else
# include <io.h>
# include <fcntl.h>
# include <windows.h>
# endif
# endif
2016-09-19 01:12:39 +02:00
# ifdef HAVE_CONFIG_H
# include "../config.h"
# endif
2016-05-16 16:42:33 +02:00
# include <boolean.h>
2016-09-19 21:18:49 -04:00
# include <encodings/crc32.h>
2016-05-16 16:42:33 +02:00
# include <compat/strl.h>
# include <compat/posix_string.h>
# include <file/file_path.h>
# include <file/archive_file.h>
# include <string/stdstring.h>
# include <retro_miscellaneous.h>
# include <streams/file_stream.h>
# include <retro_assert.h>
# include <lists/string_list.h>
# include <string/stdstring.h>
2016-09-19 01:12:39 +02:00
# ifdef HAVE_MENU
# include "../menu/menu_driver.h"
2017-01-11 03:36:35 +01:00
# include "../menu/menu_shader.h"
2016-09-19 01:12:39 +02:00
# endif
# ifdef HAVE_CHEEVOS
2017-05-07 19:06:03 +01:00
# include "../cheevos/cheevos.h"
2016-09-19 01:12:39 +02:00
# endif
# include "tasks_internal.h"
# include "../command.h"
2016-12-06 08:28:26 +01:00
# include "../core_info.h"
2016-09-19 01:12:39 +02:00
# include "../content.h"
# include "../configuration.h"
# include "../defaults.h"
# include "../frontend/frontend.h"
# include "../playlist.h"
# include "../paths.h"
# include "../retroarch.h"
# include "../verbosity.h"
2016-05-16 16:42:33 +02:00
# include "../msg_hash.h"
# include "../content.h"
# include "../dynamic.h"
# include "../retroarch.h"
# include "../file_path_special.h"
# include "../core.h"
2016-09-17 14:57:53 +02:00
# include "../dirs.h"
2016-09-17 12:35:29 +02:00
# include "../paths.h"
2016-05-16 16:42:33 +02:00
# include "../verbosity.h"
2017-01-31 05:33:13 +01:00
# include "task_patch.c"
2017-01-31 04:53:16 +01:00
2016-09-18 10:38:15 -04:00
# define MAX_ARGS 32
2017-05-13 22:35:10 +02:00
typedef struct content_stream content_stream_t ;
typedef struct content_information_ctx content_information_ctx_t ;
struct content_stream
2016-05-16 16:42:33 +02:00
{
uint32_t a ;
const uint8_t * b ;
size_t c ;
uint32_t crc ;
2017-05-13 22:35:10 +02:00
} ;
2016-05-16 16:42:33 +02:00
2017-05-13 22:35:10 +02:00
struct content_information_ctx
2016-12-20 23:12:56 +01:00
{
2016-12-20 23:39:31 +01:00
struct
{
struct retro_subsystem_info * data ;
unsigned size ;
} subsystem ;
2017-05-14 04:52:34 +02:00
char * name_ips ;
char * name_bps ;
char * name_ups ;
2016-12-20 23:12:56 +01:00
char * valid_extensions ;
2016-12-20 23:25:35 +01:00
char * directory_cache ;
2016-12-21 00:00:59 +01:00
char * directory_system ;
2017-05-14 01:12:47 +02:00
bool is_ips_pref ;
bool is_bps_pref ;
bool is_ups_pref ;
2016-12-21 00:00:59 +01:00
bool history_list_enable ;
2016-12-20 23:12:56 +01:00
bool block_extract ;
bool need_fullpath ;
2016-12-20 23:25:35 +01:00
bool set_supports_no_game_enable ;
2017-01-23 21:03:12 +01:00
bool patch_is_blocked ;
bool bios_is_missing ;
2017-02-21 19:06:08 +01:00
bool check_firmware_before_loading ;
2016-12-21 15:21:11 +01:00
struct string_list * temporary_content ;
2017-05-13 22:35:10 +02:00
} ;
2016-12-20 23:12:56 +01:00
2016-05-16 16:42:33 +02:00
static struct string_list * temporary_content = NULL ;
static bool _content_is_inited = false ;
static bool core_does_not_need_content = false ;
2017-05-06 16:41:22 +02:00
static uint32_t content_rom_crc = 0 ;
2016-05-16 16:42:33 +02:00
static int content_file_read ( const char * path , void * * buf , ssize_t * length )
{
# ifdef HAVE_COMPRESSION
2016-09-22 12:52:20 -04:00
if ( path_contains_compressed_file ( path ) )
2016-05-16 16:42:33 +02:00
{
2016-09-18 00:38:59 -04:00
if ( file_archive_compressed_read ( path , buf , NULL , length ) )
2016-05-16 16:42:33 +02:00
return 1 ;
}
# endif
return filestream_read_file ( path , buf , length ) ;
}
/**
* content_load_init_wrap :
* @ args : Input arguments .
* @ argc : Count of arguments .
* @ argv : Arguments .
*
* Generates an @ argc and @ argv pair based on @ args
* of type rarch_main_wrap .
* */
static void content_load_init_wrap (
const struct rarch_main_wrap * args ,
int * argc , char * * argv )
{
# ifdef HAVE_FILE_LOGGER
int i ;
# endif
* argc = 0 ;
argv [ ( * argc ) + + ] = strdup ( " retroarch " ) ;
2017-11-26 11:33:02 -05:00
if ( args - > content_path )
2016-05-16 16:42:33 +02:00
{
2017-11-26 11:33:02 -05:00
RARCH_LOG ( " Using content: %s. \n " , args - > content_path ) ;
argv [ ( * argc ) + + ] = strdup ( args - > content_path ) ;
}
2016-05-16 16:42:33 +02:00
# ifdef HAVE_MENU
2017-11-26 11:33:02 -05:00
else
{
RARCH_LOG ( " %s \n " ,
msg_hash_to_str ( MSG_NO_CONTENT_STARTING_DUMMY_CORE ) ) ;
argv [ ( * argc ) + + ] = strdup ( " --menu " ) ;
2016-05-16 16:42:33 +02:00
}
2016-09-12 01:10:35 +02:00
# endif
2016-05-16 16:42:33 +02:00
2017-11-26 11:33:02 -05:00
2016-05-16 16:42:33 +02:00
if ( args - > sram_path )
{
argv [ ( * argc ) + + ] = strdup ( " -s " ) ;
argv [ ( * argc ) + + ] = strdup ( args - > sram_path ) ;
}
if ( args - > state_path )
{
argv [ ( * argc ) + + ] = strdup ( " -S " ) ;
argv [ ( * argc ) + + ] = strdup ( args - > state_path ) ;
}
if ( args - > config_path )
{
argv [ ( * argc ) + + ] = strdup ( " -c " ) ;
argv [ ( * argc ) + + ] = strdup ( args - > config_path ) ;
}
# ifdef HAVE_DYNAMIC
if ( args - > libretro_path )
{
argv [ ( * argc ) + + ] = strdup ( " -L " ) ;
argv [ ( * argc ) + + ] = strdup ( args - > libretro_path ) ;
}
# endif
if ( args - > verbose )
argv [ ( * argc ) + + ] = strdup ( " -v " ) ;
# ifdef HAVE_FILE_LOGGER
for ( i = 0 ; i < * argc ; i + + )
RARCH_LOG ( " arg #%d: %s \n " , i , argv [ i ] ) ;
# endif
}
/**
* content_load :
*
* Loads content file and starts up RetroArch .
* If no content file can be loaded , will start up RetroArch
* as - is .
*
2016-09-17 21:10:42 -03:00
* Returns : false ( 0 ) if retroarch_main_init failed ,
2016-05-16 16:42:33 +02:00
* otherwise true ( 1 ) .
* */
2016-05-16 16:44:34 +02:00
static bool content_load ( content_ctx_info_t * info )
2016-05-16 16:42:33 +02:00
{
unsigned i ;
bool retval = true ;
int rarch_argc = 0 ;
char * rarch_argv [ MAX_ARGS ] = { NULL } ;
char * argv_copy [ MAX_ARGS ] = { NULL } ;
char * * rarch_argv_ptr = ( char * * ) info - > argv ;
int * rarch_argc_ptr = ( int * ) & info - > argc ;
struct rarch_main_wrap * wrap_args = ( struct rarch_main_wrap * )
calloc ( 1 , sizeof ( * wrap_args ) ) ;
if ( ! wrap_args )
return false ;
retro_assert ( wrap_args ) ;
if ( info - > environ_get )
info - > environ_get ( rarch_argc_ptr ,
rarch_argv_ptr , info - > args , wrap_args ) ;
if ( wrap_args - > touched )
{
content_load_init_wrap ( wrap_args , & rarch_argc , rarch_argv ) ;
memcpy ( argv_copy , rarch_argv , sizeof ( rarch_argv ) ) ;
rarch_argv_ptr = ( char * * ) rarch_argv ;
rarch_argc_ptr = ( int * ) & rarch_argc ;
}
rarch_ctl ( RARCH_CTL_MAIN_DEINIT , NULL ) ;
wrap_args - > argc = * rarch_argc_ptr ;
wrap_args - > argv = rarch_argv_ptr ;
if ( ! retroarch_main_init ( wrap_args - > argc , wrap_args - > argv ) )
{
retval = false ;
2017-05-14 04:50:57 +02:00
goto end ;
2016-05-16 16:42:33 +02:00
}
# ifdef HAVE_MENU
2018-01-31 23:05:42 +01:00
/* TODO/FIXME - can we get rid of this? */
2017-01-11 03:36:35 +01:00
menu_shader_manager_init ( ) ;
2016-05-16 16:42:33 +02:00
# endif
command_event ( CMD_EVENT_HISTORY_INIT , NULL ) ;
command_event ( CMD_EVENT_RESUME , NULL ) ;
command_event ( CMD_EVENT_VIDEO_SET_ASPECT_RATIO , NULL ) ;
2016-09-19 00:56:00 +02:00
dir_check_defaults ( ) ;
2016-05-16 16:42:33 +02:00
frontend_driver_process_args ( rarch_argc_ptr , rarch_argv_ptr ) ;
frontend_driver_content_loaded ( ) ;
2017-05-14 04:50:57 +02:00
end :
2016-05-16 16:42:33 +02:00
for ( i = 0 ; i < ARRAY_SIZE ( argv_copy ) ; i + + )
free ( argv_copy [ i ] ) ;
free ( wrap_args ) ;
return retval ;
}
/**
2016-09-21 04:09:24 +02:00
* load_content_into_memory :
2016-05-16 16:42:33 +02:00
* @ path : buffer of the content file .
* @ buf : size of the content file .
* @ length : size of the content file that has been read from .
*
* Read the content file . If read into memory , also performs soft patching
* ( see patch_content function ) in case soft patching has not been
* blocked by the enduser .
*
* Returns : true if successful , false on error .
* */
2017-01-23 21:03:12 +01:00
static bool load_content_into_memory (
content_information_ctx_t * content_ctx ,
unsigned i , const char * path , void * * buf ,
2016-05-16 16:42:33 +02:00
ssize_t * length )
{
uint8_t * ret_buf = NULL ;
RARCH_LOG ( " %s: %s. \n " ,
msg_hash_to_str ( MSG_LOADING_CONTENT_FILE ) , path ) ;
2017-05-14 04:50:57 +02:00
2016-05-16 16:42:33 +02:00
if ( ! content_file_read ( path , ( void * * ) & ret_buf , length ) )
return false ;
if ( * length < 0 )
return false ;
2016-09-21 04:03:31 +02:00
if ( i = = 0 )
{
2017-05-29 20:26:10 +02:00
enum rarch_content_type type = path_is_media_type ( path ) ;
/* If we have a media type, ignore CRC32 calculation. */
if ( type = = RARCH_CONTENT_NONE )
{
/* First content file is significant, attempt to do patching,
* CRC checking , etc . */
/* Attempt to apply a patch. */
if ( ! content_ctx - > patch_is_blocked )
patch_content (
content_ctx - > is_ips_pref ,
content_ctx - > is_bps_pref ,
content_ctx - > is_ups_pref ,
content_ctx - > name_ips ,
content_ctx - > name_bps ,
content_ctx - > name_ups ,
( uint8_t * * ) & ret_buf ,
( void * ) length ) ;
content_rom_crc = encoding_crc32 ( 0 , ret_buf , * length ) ;
RARCH_LOG ( " CRC32: 0x%x . \n " , ( unsigned ) content_rom_crc ) ;
}
else
content_rom_crc = 0 ;
2016-09-21 04:03:31 +02:00
}
2016-05-16 16:42:33 +02:00
* buf = ret_buf ;
return true ;
}
# ifdef HAVE_COMPRESSION
static bool load_content_from_compressed_archive (
2016-12-20 23:12:56 +01:00
content_information_ctx_t * content_ctx ,
struct retro_game_info * info ,
unsigned i ,
2016-05-16 16:42:33 +02:00
struct string_list * additional_path_allocs ,
2016-12-20 23:12:56 +01:00
bool need_fullpath ,
const char * path ,
2016-12-27 01:32:58 +01:00
char * * error_string )
2016-05-16 16:42:33 +02:00
{
union string_list_elem_attr attributes ;
ssize_t new_path_len = 0 ;
2017-09-09 23:17:28 +02:00
size_t path_size = PATH_MAX_LENGTH * sizeof ( char ) ;
char * new_basedir = ( char * ) malloc ( PATH_MAX_LENGTH * sizeof ( char ) ) ;
char * new_path = ( char * ) malloc ( PATH_MAX_LENGTH * sizeof ( char ) ) ;
2016-05-16 16:42:33 +02:00
bool ret = false ;
2016-09-06 08:38:26 +02:00
2017-02-23 21:49:51 +01:00
new_path [ 0 ] = ' \0 ' ;
new_basedir [ 0 ] = ' \0 ' ;
attributes . i = 0 ;
2016-05-16 16:42:33 +02:00
RARCH_LOG ( " Compressed file in case of need_fullpath. "
" Now extracting to temporary directory. \n " ) ;
2017-02-21 20:30:52 +01:00
if ( ! string_is_empty ( content_ctx - > directory_cache ) )
strlcpy ( new_basedir , content_ctx - > directory_cache ,
2017-09-09 23:17:28 +02:00
path_size ) ;
2016-05-16 16:42:33 +02:00
if ( string_is_empty ( new_basedir ) | | ! path_is_directory ( new_basedir ) )
{
RARCH_WARN ( " Tried extracting to cache directory, but "
" cache directory was not set or found. "
" Setting cache directory to directory "
" derived by basename... \n " ) ;
fill_pathname_basedir ( new_basedir , path ,
2017-09-09 23:17:28 +02:00
path_size ) ;
2016-05-16 16:42:33 +02:00
}
2016-10-09 09:56:03 +02:00
new_path [ 0 ] = ' \0 ' ;
new_basedir [ 0 ] = ' \0 ' ;
2016-05-16 16:42:33 +02:00
fill_pathname_join ( new_path , new_basedir ,
2017-09-09 23:17:28 +02:00
path_basename ( path ) , path_size ) ;
2016-05-16 16:42:33 +02:00
2017-09-09 23:17:28 +02:00
ret = file_archive_compressed_read ( path ,
NULL , new_path , & new_path_len ) ;
2016-05-16 16:42:33 +02:00
if ( ! ret | | new_path_len < 0 )
{
2017-09-09 23:17:28 +02:00
char * str = ( char * ) malloc ( 1024 * sizeof ( char ) ) ;
snprintf ( str ,
1024 * sizeof ( char ) ,
" %s \" %s \" . \n " ,
2016-05-16 16:42:33 +02:00
msg_hash_to_str ( MSG_COULD_NOT_READ_CONTENT_FILE ) ,
path ) ;
2016-12-27 01:32:58 +01:00
* error_string = strdup ( str ) ;
2017-09-09 23:17:28 +02:00
free ( str ) ;
goto error ;
2016-05-16 16:42:33 +02:00
}
string_list_append ( additional_path_allocs , new_path , attributes ) ;
2016-09-17 21:10:42 -03:00
info [ i ] . path =
2016-05-16 16:42:33 +02:00
additional_path_allocs - > elems [ additional_path_allocs - > size - 1 ] . data ;
2017-09-09 23:17:28 +02:00
if ( ! string_list_append ( content_ctx - > temporary_content ,
new_path , attributes ) )
goto error ;
2016-05-16 16:42:33 +02:00
2017-09-09 23:17:28 +02:00
free ( new_basedir ) ;
free ( new_path ) ;
2016-05-16 16:42:33 +02:00
return true ;
2017-09-09 23:17:28 +02:00
error :
free ( new_basedir ) ;
free ( new_path ) ;
return false ;
2016-05-16 16:42:33 +02:00
}
2016-09-19 00:56:58 +02:00
2016-12-20 22:32:54 +01:00
static bool content_file_init_extract (
2016-09-19 00:56:58 +02:00
struct string_list * content ,
2016-12-20 23:12:56 +01:00
content_information_ctx_t * content_ctx ,
2016-09-19 00:56:58 +02:00
const struct retro_subsystem_info * special ,
2016-12-20 22:32:54 +01:00
union string_list_elem_attr * attr ,
2016-12-27 01:32:58 +01:00
char * * error_string
2016-09-19 00:56:58 +02:00
)
{
unsigned i ;
2017-09-27 23:55:54 +02:00
char * new_path = NULL ;
2016-09-19 00:56:58 +02:00
for ( i = 0 ; i < content - > size ; i + + )
{
2016-09-22 16:03:23 -04:00
bool block_extract = content - > elems [ i ] . attr . i & 1 ;
2016-12-21 15:23:31 +01:00
const char * path = content - > elems [ i ] . data ;
2016-12-21 15:27:08 +01:00
bool contains_compressed = path_contains_compressed_file ( path ) ;
2016-09-19 00:56:58 +02:00
/* Block extract check. */
2016-09-22 16:03:23 -04:00
if ( block_extract )
2016-09-19 00:56:58 +02:00
continue ;
2016-12-21 15:31:55 +01:00
/* just use the first file in the archive */
if ( ! contains_compressed & & ! path_is_compressed_file ( path ) )
continue ;
2016-09-19 00:56:58 +02:00
{
2017-09-27 23:55:54 +02:00
char * temp_content = ( char * ) malloc ( PATH_MAX_LENGTH * sizeof ( char ) ) ;
const char * valid_ext = special ?
2017-09-10 21:42:24 +02:00
special - > roms [ i ] . valid_extensions :
content_ctx - > valid_extensions ;
2017-09-27 23:55:54 +02:00
new_path = ( char * ) malloc ( PATH_MAX_LENGTH * sizeof ( char ) ) ;
2017-09-10 21:42:24 +02:00
temp_content [ 0 ] = new_path [ 0 ] = ' \0 ' ;
2017-12-28 05:56:45 +01:00
if ( ! string_is_empty ( path ) )
strlcpy ( temp_content , path ,
PATH_MAX_LENGTH * sizeof ( char ) ) ;
2017-09-10 21:42:24 +02:00
if ( ! valid_ext | | ! file_archive_extract_file (
temp_content ,
PATH_MAX_LENGTH * sizeof ( char ) ,
valid_ext ,
! string_is_empty ( content_ctx - > directory_cache ) ?
content_ctx - > directory_cache : NULL ,
new_path ,
PATH_MAX_LENGTH * sizeof ( char )
) )
{
char * str = ( char * ) malloc ( 1024 * sizeof ( char ) ) ;
snprintf ( str , 1024 * sizeof ( char ) ,
" %s: %s. \n " ,
msg_hash_to_str (
MSG_FAILED_TO_EXTRACT_CONTENT_FROM_COMPRESSED_FILE ) ,
temp_content ) ;
free ( temp_content ) ;
free ( str ) ;
goto error ;
}
2016-12-20 22:32:54 +01:00
2017-09-10 21:42:24 +02:00
string_list_set ( content , i , new_path ) ;
2016-09-19 00:56:58 +02:00
2017-09-10 21:42:24 +02:00
free ( temp_content ) ;
2016-12-21 15:27:08 +01:00
2017-09-10 21:42:24 +02:00
if ( ! string_list_append ( content_ctx - > temporary_content ,
new_path , * attr ) )
goto error ;
free ( new_path ) ;
}
2016-09-19 00:56:58 +02:00
}
return true ;
2017-09-10 21:42:24 +02:00
error :
2017-09-27 23:54:31 +02:00
free ( new_path ) ;
2017-09-10 21:42:24 +02:00
return false ;
2016-09-19 00:56:58 +02:00
}
2016-05-16 16:42:33 +02:00
# endif
/**
2016-12-20 22:35:59 +01:00
* content_file_load :
2016-05-16 16:42:33 +02:00
* @ special : subsystem of content to be loaded . Can be NULL .
* content :
*
* Load content file ( for libretro core ) .
*
* Returns : true if successful , otherwise false .
* */
2016-12-20 22:35:59 +01:00
static bool content_file_load (
2016-05-16 16:42:33 +02:00
struct retro_game_info * info ,
const struct string_list * content ,
2016-12-20 23:12:56 +01:00
content_information_ctx_t * content_ctx ,
2016-12-27 01:32:58 +01:00
char * * error_string ,
2017-05-14 05:06:01 +02:00
const struct retro_subsystem_info * special ,
struct string_list * additional_path_allocs
2016-05-16 16:42:33 +02:00
)
{
unsigned i ;
retro_ctx_load_content_info_t load_info ;
2017-09-09 23:17:28 +02:00
size_t msg_size = 1024 * sizeof ( char ) ;
char * msg = ( char * ) malloc ( 1024 * sizeof ( char ) ) ;
2016-05-16 16:42:33 +02:00
2017-09-09 23:17:28 +02:00
msg [ 0 ] = ' \0 ' ;
2016-12-21 00:16:25 +01:00
2016-05-16 16:42:33 +02:00
for ( i = 0 ; i < content - > size ; i + + )
{
int attr = content - > elems [ i ] . attr . i ;
2016-12-21 00:16:25 +01:00
const char * path = content - > elems [ i ] . data ;
2016-05-16 16:42:33 +02:00
bool need_fullpath = attr & 2 ;
bool require_content = attr & 4 ;
if ( require_content & & string_is_empty ( path ) )
{
2017-01-25 02:05:42 +01:00
strlcpy ( msg ,
msg_hash_to_str ( MSG_ERROR_LIBRETRO_CORE_REQUIRES_CONTENT ) ,
2017-12-11 23:55:31 -08:00
msg_size
2017-01-25 02:05:42 +01:00
) ;
2016-12-27 01:32:58 +01:00
* error_string = strdup ( msg ) ;
2017-09-09 23:17:28 +02:00
goto error ;
2016-05-16 16:42:33 +02:00
}
info [ i ] . path = NULL ;
2016-06-28 10:50:00 +02:00
if ( ! string_is_empty ( path ) )
2016-05-16 16:42:33 +02:00
info [ i ] . path = path ;
if ( ! need_fullpath & & ! string_is_empty ( path ) )
{
2016-09-21 04:09:24 +02:00
/* Load the content into memory. */
ssize_t len = 0 ;
2016-09-22 16:03:23 -04:00
2017-01-23 21:03:12 +01:00
if ( ! load_content_into_memory (
content_ctx ,
i , path , ( void * * ) & info [ i ] . data , & len ) )
2016-09-21 04:09:24 +02:00
{
2017-09-09 23:17:28 +02:00
snprintf ( msg ,
msg_size ,
2016-12-21 00:16:25 +01:00
" %s \" %s \" . \n " ,
2016-09-21 04:09:24 +02:00
msg_hash_to_str ( MSG_COULD_NOT_READ_CONTENT_FILE ) ,
path ) ;
2016-12-27 01:32:58 +01:00
* error_string = strdup ( msg ) ;
2017-09-09 23:17:28 +02:00
goto error ;
2016-09-21 04:09:24 +02:00
}
info [ i ] . size = len ;
2016-05-16 16:42:33 +02:00
}
else
{
2016-06-20 04:17:03 +02:00
RARCH_LOG ( " %s \n " ,
2016-07-01 08:35:12 +02:00
msg_hash_to_str (
MSG_CONTENT_LOADING_SKIPPED_IMPLEMENTATION_WILL_DO_IT ) ) ;
2016-05-16 16:42:33 +02:00
# ifdef HAVE_COMPRESSION
2016-12-21 15:30:14 +01:00
if ( ! content_ctx - > block_extract
& & need_fullpath
& & path_contains_compressed_file ( path )
& & ! load_content_from_compressed_archive (
2016-12-20 23:12:56 +01:00
content_ctx ,
2016-05-16 16:42:33 +02:00
& info [ i ] , i ,
2016-12-20 22:32:54 +01:00
additional_path_allocs , need_fullpath , path ,
error_string ) )
2017-09-09 23:17:28 +02:00
goto error ;
2016-05-16 16:42:33 +02:00
# endif
}
}
load_info . content = content ;
load_info . special = special ;
load_info . info = info ;
if ( ! core_load_game ( & load_info ) )
{
2017-09-09 23:17:28 +02:00
snprintf ( msg ,
msg_size ,
2017-01-25 02:05:42 +01:00
" %s. " , msg_hash_to_str ( MSG_FAILED_TO_LOAD_CONTENT ) ) ;
2016-12-27 01:32:58 +01:00
* error_string = strdup ( msg ) ;
2017-09-09 23:17:28 +02:00
goto error ;
2016-05-16 16:42:33 +02:00
}
# ifdef HAVE_CHEEVOS
if ( ! special )
{
2017-05-29 20:26:10 +02:00
const char * content_path = content - > elems [ 0 ] . data ;
enum rarch_content_type type = path_is_media_type ( content_path ) ;
2016-05-16 16:42:33 +02:00
cheevos_set_cheats ( ) ;
2017-05-29 20:26:10 +02:00
if ( type = = RARCH_CONTENT_NONE & & ! string_is_empty ( content_path ) )
2017-05-07 19:06:03 +01:00
cheevos_load ( info ) ;
2016-05-16 16:42:33 +02:00
}
# endif
2017-09-09 23:17:28 +02:00
free ( msg ) ;
2016-05-16 16:42:33 +02:00
return true ;
2017-09-09 23:17:28 +02:00
error :
free ( msg ) ;
return false ;
2016-05-16 16:42:33 +02:00
}
2017-12-11 23:55:31 -08:00
static const struct
2017-09-09 23:17:28 +02:00
retro_subsystem_info * content_file_init_subsystem (
2016-12-20 23:12:56 +01:00
content_information_ctx_t * content_ctx ,
2016-12-27 01:32:58 +01:00
char * * error_string ,
2016-12-20 23:12:56 +01:00
bool * ret )
2016-05-16 16:42:33 +02:00
{
2017-09-09 23:17:28 +02:00
size_t path_size = 1024 * sizeof ( char ) ;
char * msg = ( char * ) malloc ( 1024 * sizeof ( char ) ) ;
2016-09-25 15:49:09 +02:00
struct string_list * subsystem = path_get_subsystem_list ( ) ;
2016-12-20 23:39:31 +01:00
const struct retro_subsystem_info * special = libretro_find_subsystem_info (
content_ctx - > subsystem . data , content_ctx - > subsystem . size ,
2016-12-20 23:25:35 +01:00
path_get ( RARCH_PATH_SUBSYSTEM ) ) ;
2016-05-16 16:42:33 +02:00
2016-12-21 00:19:22 +01:00
msg [ 0 ] = ' \0 ' ;
2016-05-16 16:42:33 +02:00
if ( ! special )
{
2017-09-09 23:17:28 +02:00
snprintf ( msg , path_size ,
2016-05-16 16:42:33 +02:00
" Failed to find subsystem \" %s \" in libretro implementation. \n " ,
2016-09-29 08:23:41 +02:00
path_get ( RARCH_PATH_SUBSYSTEM ) ) ;
2016-12-27 01:32:58 +01:00
* error_string = strdup ( msg ) ;
2016-05-16 16:42:33 +02:00
goto error ;
}
2016-09-25 15:49:09 +02:00
if ( special - > num_roms & & ! subsystem )
2016-05-16 16:42:33 +02:00
{
2017-01-25 02:05:42 +01:00
strlcpy ( msg ,
msg_hash_to_str ( MSG_ERROR_LIBRETRO_CORE_REQUIRES_SPECIAL_CONTENT ) ,
2017-12-11 23:55:31 -08:00
path_size
2017-01-25 02:05:42 +01:00
) ;
2016-12-27 01:32:58 +01:00
* error_string = strdup ( msg ) ;
2016-05-16 16:42:33 +02:00
goto error ;
}
2016-09-25 15:49:09 +02:00
else if ( special - > num_roms & & ( special - > num_roms ! = subsystem - > size ) )
2016-05-16 16:42:33 +02:00
{
2017-09-09 23:17:28 +02:00
snprintf ( msg ,
path_size ,
2016-12-21 00:19:22 +01:00
" Libretro core requires %u content files for "
2016-05-16 16:42:33 +02:00
" subsystem \" %s \" , but %u content files were provided. \n " ,
special - > num_roms , special - > desc ,
2016-09-25 15:49:09 +02:00
( unsigned ) subsystem - > size ) ;
2016-12-27 01:32:58 +01:00
* error_string = strdup ( msg ) ;
2016-05-16 16:42:33 +02:00
goto error ;
}
2016-09-25 15:49:09 +02:00
else if ( ! special - > num_roms & & subsystem & & subsystem - > size )
2016-05-16 16:42:33 +02:00
{
2017-09-09 23:17:28 +02:00
snprintf ( msg ,
path_size ,
2016-12-21 00:19:22 +01:00
" Libretro core takes no content for subsystem \" %s \" , "
2016-05-16 16:42:33 +02:00
" but %u content files were provided. \n " ,
special - > desc ,
2016-09-25 15:49:09 +02:00
( unsigned ) subsystem - > size ) ;
2016-12-27 01:32:58 +01:00
* error_string = strdup ( msg ) ;
2016-05-16 16:42:33 +02:00
goto error ;
}
* ret = true ;
2017-09-09 23:17:28 +02:00
free ( msg ) ;
2016-05-16 16:42:33 +02:00
return special ;
error :
* ret = false ;
2017-09-09 23:17:28 +02:00
free ( msg ) ;
2016-05-16 16:42:33 +02:00
return NULL ;
}
2016-12-20 22:03:04 +01:00
static bool content_file_init_set_attribs (
2016-05-16 16:42:33 +02:00
struct string_list * content ,
2016-12-20 22:32:54 +01:00
const struct retro_subsystem_info * special ,
2016-12-20 23:12:56 +01:00
content_information_ctx_t * content_ctx ,
2016-12-27 01:32:58 +01:00
char * * error_string )
2016-05-16 16:42:33 +02:00
{
union string_list_elem_attr attr ;
2016-09-25 15:49:09 +02:00
struct string_list * subsystem = path_get_subsystem_list ( ) ;
2016-05-16 16:42:33 +02:00
2016-09-25 15:49:09 +02:00
attr . i = 0 ;
2016-05-16 16:42:33 +02:00
2016-09-30 04:43:16 +02:00
if ( ! path_is_empty ( RARCH_PATH_SUBSYSTEM ) & & special )
2016-05-16 16:42:33 +02:00
{
unsigned i ;
2016-09-25 15:49:09 +02:00
for ( i = 0 ; i < subsystem - > size ; i + + )
2016-05-16 16:42:33 +02:00
{
attr . i = special - > roms [ i ] . block_extract ;
attr . i | = special - > roms [ i ] . need_fullpath < < 1 ;
attr . i | = special - > roms [ i ] . required < < 2 ;
2016-09-25 15:49:09 +02:00
string_list_append ( content , subsystem - > elems [ i ] . data , attr ) ;
2016-05-16 16:42:33 +02:00
}
}
else
{
2017-01-25 15:44:21 +01:00
bool contentless = false ;
2017-01-25 15:51:57 +01:00
bool is_inited = false ;
2017-01-25 15:44:21 +01:00
2017-01-25 15:51:57 +01:00
content_get_status ( & contentless , & is_inited ) ;
2017-01-25 15:44:21 +01:00
2016-12-20 23:12:56 +01:00
attr . i = content_ctx - > block_extract ;
attr . i | = content_ctx - > need_fullpath < < 1 ;
2017-01-25 15:44:21 +01:00
attr . i | = ( ! contentless ) < < 2 ;
2016-05-16 16:42:33 +02:00
2016-10-03 15:39:48 +02:00
if ( path_is_empty ( RARCH_PATH_CONTENT )
2017-12-11 23:55:31 -08:00
& & contentless
2016-12-20 23:25:35 +01:00
& & content_ctx - > set_supports_no_game_enable )
2016-05-16 16:42:33 +02:00
string_list_append ( content , " " , attr ) ;
else
{
2016-10-03 15:39:48 +02:00
if ( ! path_is_empty ( RARCH_PATH_CONTENT ) )
string_list_append ( content , path_get ( RARCH_PATH_CONTENT ) , attr ) ;
2016-05-16 16:42:33 +02:00
}
}
2016-09-18 00:38:59 -04:00
# ifdef HAVE_COMPRESSION
2016-05-16 16:42:33 +02:00
/* Try to extract all content we're going to load if appropriate. */
2016-12-21 15:21:11 +01:00
content_file_init_extract ( content , content_ctx , special , & attr , error_string ) ;
2016-05-16 16:42:33 +02:00
# endif
return true ;
}
/**
* content_init_file :
*
* Initializes and loads a content file for the currently
* selected libretro core .
*
* Returns : true if successful , otherwise false .
* */
2016-12-21 15:21:11 +01:00
static bool content_file_init (
2016-12-20 23:12:56 +01:00
content_information_ctx_t * content_ctx ,
2017-05-14 20:23:10 +02:00
struct string_list * content ,
2016-12-27 01:32:58 +01:00
char * * error_string )
2016-05-16 16:42:33 +02:00
{
struct retro_game_info * info = NULL ;
2017-12-11 23:55:31 -08:00
bool ret =
path_is_empty ( RARCH_PATH_SUBSYSTEM )
2016-12-20 23:36:39 +01:00
? true : false ;
2017-12-11 23:55:31 -08:00
const struct retro_subsystem_info * special =
path_is_empty ( RARCH_PATH_SUBSYSTEM )
2016-12-21 00:19:22 +01:00
? NULL : content_file_init_subsystem ( content_ctx , error_string , & ret ) ;
2016-05-16 16:42:33 +02:00
2017-12-11 23:55:31 -08:00
if ( ! ret | |
2017-05-14 20:23:10 +02:00
! content_file_init_set_attribs ( content , special , content_ctx , error_string ) )
2017-05-14 04:50:57 +02:00
return false ;
2016-05-16 16:42:33 +02:00
info = ( struct retro_game_info * )
calloc ( content - > size , sizeof ( * info ) ) ;
2016-09-29 12:02:45 +02:00
if ( info )
2016-09-29 19:24:18 +02:00
{
unsigned i ;
2017-05-14 05:06:01 +02:00
struct string_list * additional_path_allocs = string_list_new ( ) ;
2016-12-21 15:21:11 +01:00
ret = content_file_load ( info , content , content_ctx , error_string ,
2017-05-14 05:06:01 +02:00
special , additional_path_allocs ) ;
string_list_free ( additional_path_allocs ) ;
2016-05-16 16:42:33 +02:00
2016-09-29 19:24:18 +02:00
for ( i = 0 ; i < content - > size ; i + + )
free ( ( void * ) info [ i ] . data ) ;
2016-05-16 16:42:33 +02:00
free ( info ) ;
2016-09-29 19:24:18 +02:00
}
2016-05-16 16:42:33 +02:00
return ret ;
}
2016-05-16 15:09:04 +02:00
# ifdef HAVE_MENU
static void menu_content_environment_get ( int * argc , char * argv [ ] ,
void * args , void * params_data )
{
2016-06-03 05:24:14 +02:00
struct rarch_main_wrap * wrap_args = ( struct rarch_main_wrap * ) params_data ;
2017-05-28 17:21:57 +02:00
rarch_system_info_t * sys_info = runloop_get_system_info ( ) ;
2016-09-17 21:10:42 -03:00
2016-05-16 15:09:04 +02:00
if ( ! wrap_args )
return ;
2017-05-28 17:21:57 +02:00
wrap_args - > no_content = sys_info - > load_no_content ;
2016-05-16 15:09:04 +02:00
2016-10-01 06:05:08 +02:00
if ( ! retroarch_override_setting_is_set ( RARCH_OVERRIDE_SETTING_VERBOSITY , NULL ) )
2016-05-31 04:42:04 +02:00
wrap_args - > verbose = verbosity_is_enabled ( ) ;
2016-05-16 15:09:04 +02:00
wrap_args - > touched = true ;
wrap_args - > config_path = NULL ;
wrap_args - > sram_path = NULL ;
wrap_args - > state_path = NULL ;
wrap_args - > content_path = NULL ;
2016-09-30 04:43:16 +02:00
if ( ! path_is_empty ( RARCH_PATH_CONFIG ) )
2016-09-29 08:31:41 +02:00
wrap_args - > config_path = path_get ( RARCH_PATH_CONFIG ) ;
2016-10-01 23:30:09 +02:00
if ( ! dir_is_empty ( RARCH_DIR_SAVEFILE ) )
2016-10-03 08:15:41 +02:00
wrap_args - > sram_path = dir_get ( RARCH_DIR_SAVEFILE ) ;
2016-10-01 23:30:09 +02:00
if ( ! dir_is_empty ( RARCH_DIR_SAVESTATE ) )
2016-10-03 08:15:41 +02:00
wrap_args - > state_path = dir_get ( RARCH_DIR_SAVESTATE ) ;
2016-10-03 15:39:48 +02:00
if ( ! path_is_empty ( RARCH_PATH_CONTENT ) )
wrap_args - > content_path = path_get ( RARCH_PATH_CONTENT ) ;
2016-10-01 06:05:08 +02:00
if ( ! retroarch_override_setting_is_set ( RARCH_OVERRIDE_SETTING_LIBRETRO , NULL ) )
2016-09-29 08:23:41 +02:00
wrap_args - > libretro_path = string_is_empty ( path_get ( RARCH_PATH_CORE ) ) ? NULL :
path_get ( RARCH_PATH_CORE ) ;
2016-05-16 15:09:04 +02:00
}
2016-05-16 16:32:18 +02:00
# endif
2016-05-17 07:53:38 +02:00
2016-05-16 15:09:04 +02:00
/**
2016-05-28 23:16:57 +02:00
* task_load_content :
2016-05-16 15:09:04 +02:00
*
* Loads content into currently selected core .
* Will also optionally push the content entry to the history playlist .
*
* Returns : true ( 1 ) if successful , otherwise false ( 0 ) .
* */
2016-09-17 21:10:42 -03:00
static bool task_load_content ( content_ctx_info_t * content_info ,
2016-12-21 00:00:59 +01:00
content_information_ctx_t * content_ctx ,
2016-07-30 21:19:47 +02:00
bool launched_from_menu ,
2018-02-05 16:42:02 +01:00
bool launched_from_cli ,
2016-12-27 01:32:58 +01:00
char * * error_string )
2016-05-16 15:09:04 +02:00
{
2017-01-25 15:44:21 +01:00
bool contentless = false ;
2017-01-25 15:51:57 +01:00
bool is_inited = false ;
2016-10-09 09:56:03 +02:00
2016-07-23 11:12:06 +10:00
if ( ! content_load ( content_info ) )
2017-05-14 04:50:57 +02:00
{
2018-02-05 15:37:43 +01:00
* error_string = strdup ( " This core requires a content file, could not load content. \n " ) ;
2017-05-14 04:50:57 +02:00
return false ;
}
2016-07-23 11:12:06 +10:00
2017-01-25 15:51:57 +01:00
content_get_status ( & contentless , & is_inited ) ;
2016-05-17 08:19:50 +02:00
/* Push entry to top of history playlist */
2017-01-25 15:51:57 +01:00
if ( is_inited | | contentless )
2016-05-17 07:36:18 +02:00
{
2017-09-10 21:42:24 +02:00
char * tmp = ( char * ) malloc ( PATH_MAX_LENGTH * sizeof ( char ) ) ;
2017-05-30 01:44:49 +02:00
struct retro_system_info * info = NULL ;
2017-04-23 16:41:26 +02:00
rarch_system_info_t * sys_info = runloop_get_system_info ( ) ;
2017-12-28 05:56:45 +01:00
const char * path_content = path_get ( RARCH_PATH_CONTENT ) ;
2016-05-17 08:19:50 +02:00
2016-10-09 09:56:03 +02:00
tmp [ 0 ] = ' \0 ' ;
2016-12-20 22:55:58 +01:00
if ( sys_info )
2017-05-30 01:44:49 +02:00
info = & sys_info - > info ;
2016-05-17 08:19:50 +02:00
2017-12-28 05:56:45 +01:00
if ( ! string_is_empty ( path_content ) )
strlcpy ( tmp , path_content , PATH_MAX_LENGTH * sizeof ( char ) ) ;
2016-05-17 08:19:50 +02:00
if ( ! launched_from_menu )
{
/* Path can be relative here.
* Ensure we ' re pushing absolute path . */
2016-06-28 10:50:00 +02:00
if ( ! string_is_empty ( tmp ) )
2017-09-10 21:42:24 +02:00
path_resolve_realpath ( tmp ,
PATH_MAX_LENGTH * sizeof ( char ) ) ;
2016-05-17 08:19:50 +02:00
}
2018-02-05 16:42:02 +01:00
# ifdef HAVE_MENU
/* Push quick menu onto menu stack */
if ( launched_from_cli )
menu_driver_ctl ( RARCH_MENU_CTL_SET_PENDING_QUICK_MENU , NULL ) ;
# endif
2016-12-21 00:06:34 +01:00
if ( info & & ! string_is_empty ( tmp ) )
2016-05-17 08:19:50 +02:00
{
2016-12-21 00:06:34 +01:00
const char * core_path = NULL ;
const char * core_name = NULL ;
2017-11-08 19:41:13 -08:00
const char * label = NULL ;
2016-12-21 00:06:34 +01:00
playlist_t * playlist_tmp = g_defaults . content_history ;
2017-11-08 19:41:13 -08:00
global_t * global = global_get_ptr ( ) ;
2016-07-30 21:27:40 +02:00
2016-09-17 12:56:19 +02:00
switch ( path_is_media_type ( tmp ) )
2016-07-30 22:57:32 +02:00
{
2016-07-30 23:50:29 +02:00
case RARCH_CONTENT_MOVIE :
2016-07-30 22:57:32 +02:00
# ifdef HAVE_FFMPEG
2016-12-21 00:06:34 +01:00
playlist_tmp = g_defaults . video_history ;
core_name = " movieplayer " ;
core_path = " builtin " ;
2016-07-30 23:50:29 +02:00
# endif
break ;
case RARCH_CONTENT_MUSIC :
2016-12-21 00:06:34 +01:00
playlist_tmp = g_defaults . music_history ;
core_name = " musicplayer " ;
core_path = " builtin " ;
2016-07-30 22:57:32 +02:00
break ;
2016-07-30 23:50:29 +02:00
case RARCH_CONTENT_IMAGE :
2016-07-30 22:57:32 +02:00
# ifdef HAVE_IMAGEVIEWER
2016-12-21 00:06:34 +01:00
playlist_tmp = g_defaults . image_history ;
core_name = " imageviewer " ;
core_path = " builtin " ;
2016-07-30 22:57:32 +02:00
# endif
break ;
default :
2016-09-29 08:23:41 +02:00
core_path = path_get ( RARCH_PATH_CORE ) ;
2016-07-30 23:50:29 +02:00
core_name = info - > library_name ;
2016-07-30 22:57:32 +02:00
break ;
}
2018-02-05 16:42:02 +01:00
if ( launched_from_cli )
2016-12-22 02:42:22 +01:00
{
2017-10-22 07:35:17 -07:00
settings_t * settings = config_get_ptr ( ) ;
2017-04-28 13:43:47 +02:00
content_ctx - > history_list_enable = settings - > bools . history_list_enable ;
2016-12-22 02:42:22 +01:00
}
2017-11-08 19:41:13 -08:00
if ( global & & ! string_is_empty ( global - > name . label ) )
label = global - > name . label ;
2016-12-20 22:48:10 +01:00
if (
2017-12-11 23:55:31 -08:00
content_ctx - > history_list_enable
2017-11-25 23:06:25 +01:00
& & playlist_tmp )
command_playlist_push_write (
2016-12-20 22:48:10 +01:00
playlist_tmp ,
tmp ,
2017-11-08 19:41:13 -08:00
label ,
2016-12-20 22:48:10 +01:00
core_path ,
2017-11-25 23:06:25 +01:00
core_name ) ;
2016-05-17 08:19:50 +02:00
}
2017-09-10 21:42:24 +02:00
free ( tmp ) ;
2016-05-16 15:09:04 +02:00
}
return true ;
}
2017-04-23 17:48:45 +02:00
# ifdef HAVE_MENU
2016-07-30 21:19:47 +02:00
static bool command_event_cmd_exec ( const char * data ,
2016-12-21 00:00:59 +01:00
content_information_ctx_t * content_ctx ,
2018-02-05 16:42:02 +01:00
bool launched_from_cli ,
2016-12-27 01:32:58 +01:00
char * * error_string )
2016-05-16 14:58:08 +02:00
{
2016-05-26 06:41:28 +02:00
# if defined(HAVE_DYNAMIC)
2016-05-16 16:25:16 +02:00
content_ctx_info_t content_info ;
2016-05-16 14:58:08 +02:00
2016-05-16 16:25:16 +02:00
content_info . argc = 0 ;
content_info . argv = NULL ;
content_info . args = NULL ;
2017-02-21 04:50:26 +01:00
content_info . environ_get = NULL ;
2016-05-16 16:25:16 +02:00
content_info . environ_get = menu_content_environment_get ;
2016-05-17 08:02:13 +02:00
# endif
2016-05-16 16:25:16 +02:00
2017-09-07 11:50:10 -04:00
if ( path_get ( RARCH_PATH_CONTENT ) ! = data )
2016-05-16 14:58:08 +02:00
{
2016-09-30 04:31:19 +02:00
path_clear ( RARCH_PATH_CONTENT ) ;
2016-07-30 21:19:47 +02:00
if ( ! string_is_empty ( data ) )
2016-09-29 07:40:14 +02:00
path_set ( RARCH_PATH_CONTENT , data ) ;
2016-05-16 14:58:08 +02:00
}
# if defined(HAVE_DYNAMIC)
2016-12-21 00:00:59 +01:00
if ( ! task_load_content ( & content_info , content_ctx ,
2018-02-05 16:42:02 +01:00
true , launched_from_cli , error_string ) )
2016-05-16 14:58:08 +02:00
return false ;
# else
frontend_driver_set_fork ( FRONTEND_FORK_CORE_WITH_ARGS ) ;
# endif
return true ;
}
2017-04-23 17:48:45 +02:00
# endif
2016-05-16 14:58:08 +02:00
2017-02-21 18:58:03 +01:00
static bool firmware_update_status (
2016-12-21 00:00:59 +01:00
content_information_ctx_t * content_ctx )
2016-12-06 08:28:26 +01:00
{
core_info_ctx_firmware_t firmware_info ;
core_info_t * core_info = NULL ;
2017-09-09 23:17:28 +02:00
size_t s_size = PATH_MAX_LENGTH * sizeof ( char ) ;
char * s = ( char * ) malloc ( PATH_MAX_LENGTH * sizeof ( char ) ) ;
2016-12-06 08:28:26 +01:00
core_info_get_current_core ( & core_info ) ;
2016-12-20 23:45:37 +01:00
if ( ! core_info )
2017-09-09 23:17:28 +02:00
goto error ;
2016-12-06 08:28:26 +01:00
firmware_info . path = core_info - > path ;
2016-12-20 22:51:29 +01:00
2016-12-21 00:00:59 +01:00
if ( ! string_is_empty ( content_ctx - > directory_system ) )
firmware_info . directory . system = content_ctx - > directory_system ;
2016-12-06 08:28:26 +01:00
else
{
2017-09-09 23:17:28 +02:00
strlcpy ( s , path_get ( RARCH_PATH_CONTENT ) , s_size ) ;
2016-12-17 11:54:46 +01:00
path_basedir_wrapper ( s ) ;
2016-12-06 08:28:26 +01:00
firmware_info . directory . system = s ;
}
2017-09-09 23:17:28 +02:00
RARCH_LOG ( " Updating firmware status for: %s on %s \n " ,
2017-12-11 23:55:31 -08:00
core_info - > path ,
2016-12-06 08:28:26 +01:00
firmware_info . directory . system ) ;
core_info_list_update_missing_firmware ( & firmware_info ) ;
2017-02-21 18:51:47 +01:00
if (
2017-12-11 23:55:31 -08:00
content_ctx - > bios_is_missing & &
2017-02-21 19:06:08 +01:00
content_ctx - > check_firmware_before_loading )
2017-02-21 18:51:47 +01:00
{
2017-09-09 23:17:28 +02:00
runloop_msg_queue_push (
msg_hash_to_str ( MSG_FIRMWARE ) ,
100 , 500 , true ) ;
RARCH_LOG ( " Load content blocked. Reason: %s \n " ,
msg_hash_to_str ( MSG_FIRMWARE ) ) ;
2017-02-21 18:51:47 +01:00
2017-09-09 23:17:28 +02:00
free ( s ) ;
2017-02-21 18:51:47 +01:00
return true ;
}
2017-09-09 23:17:28 +02:00
error :
free ( s ) ;
2017-02-21 18:51:47 +01:00
return false ;
2016-12-06 08:28:26 +01:00
}
2017-02-21 16:50:39 +01:00
bool task_push_start_dummy_core ( content_ctx_info_t * content_info )
2017-02-21 03:32:52 +01:00
{
content_information_ctx_t content_ctx ;
2017-05-14 05:00:24 +02:00
bool ret = true ;
2017-02-21 03:32:52 +01:00
char * error_string = NULL ;
2017-05-14 05:00:24 +02:00
global_t * global = global_get_ptr ( ) ;
2017-02-21 03:32:52 +01:00
settings_t * settings = config_get_ptr ( ) ;
2017-05-28 17:21:57 +02:00
rarch_system_info_t * sys_info = runloop_get_system_info ( ) ;
2017-02-21 03:32:52 +01:00
if ( ! content_info )
return false ;
2017-02-21 19:06:08 +01:00
2017-04-28 13:43:47 +02:00
content_ctx . check_firmware_before_loading = settings - > bools . check_firmware_before_loading ;
2017-05-14 01:12:47 +02:00
content_ctx . is_ips_pref = rarch_ctl ( RARCH_CTL_IS_IPS_PREF , NULL ) ;
content_ctx . is_bps_pref = rarch_ctl ( RARCH_CTL_IS_BPS_PREF , NULL ) ;
content_ctx . is_ups_pref = rarch_ctl ( RARCH_CTL_IS_UPS_PREF , NULL ) ;
2017-02-21 03:32:52 +01:00
content_ctx . patch_is_blocked = rarch_ctl ( RARCH_CTL_IS_PATCH_BLOCKED , NULL ) ;
2017-05-15 05:06:23 +02:00
content_ctx . bios_is_missing = rarch_ctl ( RARCH_CTL_IS_MISSING_BIOS , NULL ) ;
2017-02-21 03:32:52 +01:00
content_ctx . directory_system = NULL ;
content_ctx . directory_cache = NULL ;
2017-05-14 04:52:34 +02:00
content_ctx . name_ips = NULL ;
content_ctx . name_bps = NULL ;
content_ctx . name_ups = NULL ;
2017-02-21 03:32:52 +01:00
content_ctx . valid_extensions = NULL ;
content_ctx . block_extract = false ;
content_ctx . need_fullpath = false ;
content_ctx . set_supports_no_game_enable = false ;
content_ctx . subsystem . data = NULL ;
content_ctx . subsystem . size = 0 ;
2017-04-28 13:43:47 +02:00
content_ctx . history_list_enable = settings - > bools . history_list_enable ;
2017-02-21 03:32:52 +01:00
2017-05-14 05:00:24 +02:00
if ( global )
{
if ( ! string_is_empty ( global - > name . ips ) )
content_ctx . name_ips = strdup ( global - > name . ips ) ;
if ( ! string_is_empty ( global - > name . bps ) )
content_ctx . name_bps = strdup ( global - > name . bps ) ;
if ( ! string_is_empty ( global - > name . ups ) )
content_ctx . name_ups = strdup ( global - > name . ups ) ;
}
2017-04-29 00:39:29 +02:00
if ( ! string_is_empty ( settings - > paths . directory_system ) )
content_ctx . directory_system = strdup ( settings - > paths . directory_system ) ;
2017-02-21 03:32:52 +01:00
# ifdef HAVE_MENU
if ( ! content_info - > environ_get )
content_info - > environ_get = menu_content_environment_get ;
# endif
/* Clear content path */
path_clear ( RARCH_PATH_CONTENT ) ;
/* Preliminary stuff that has to be done before we
* load the actual content . Can differ per mode . */
2017-05-28 17:21:57 +02:00
sys_info - > load_no_content = false ;
2017-05-15 05:06:23 +02:00
rarch_ctl ( RARCH_CTL_STATE_FREE , NULL ) ;
rarch_ctl ( RARCH_CTL_DATA_DEINIT , NULL ) ;
rarch_ctl ( RARCH_CTL_TASK_INIT , NULL ) ;
2017-02-21 03:32:52 +01:00
/* Load content */
if ( ! task_load_content ( content_info , & content_ctx ,
2017-02-21 05:31:34 +01:00
false , false , & error_string ) )
2017-05-14 04:50:57 +02:00
{
if ( error_string )
{
runloop_msg_queue_push ( error_string , 2 , 90 , true ) ;
2017-11-26 00:57:02 +01:00
RARCH_ERR ( " %s \n " , error_string ) ;
2017-05-14 04:50:57 +02:00
free ( error_string ) ;
}
2017-02-21 03:32:52 +01:00
2017-05-14 05:00:24 +02:00
ret = false ;
2017-02-21 03:32:52 +01:00
}
2017-05-14 05:00:24 +02:00
if ( content_ctx . name_ips )
free ( content_ctx . name_ips ) ;
if ( content_ctx . name_bps )
free ( content_ctx . name_bps ) ;
if ( content_ctx . name_ups )
free ( content_ctx . name_ups ) ;
2017-02-21 03:32:52 +01:00
if ( content_ctx . directory_system )
free ( content_ctx . directory_system ) ;
2017-05-14 05:00:24 +02:00
return ret ;
2017-02-21 03:32:52 +01:00
}
2017-02-21 18:55:11 +01:00
# ifdef HAVE_MENU
2017-02-21 18:36:38 +01:00
bool task_push_load_content_from_playlist_from_menu (
2017-02-21 03:44:36 +01:00
const char * core_path ,
const char * fullpath ,
2017-11-08 19:41:13 -08:00
const char * label ,
2017-02-21 03:44:36 +01:00
content_ctx_info_t * content_info ,
retro_task_callback_t cb ,
void * user_data )
{
content_information_ctx_t content_ctx ;
2017-12-11 23:55:31 -08:00
2017-05-14 05:00:24 +02:00
bool ret = true ;
2017-02-21 03:44:36 +01:00
char * error_string = NULL ;
2017-05-14 05:00:24 +02:00
global_t * global = global_get_ptr ( ) ;
2017-02-21 03:44:36 +01:00
settings_t * settings = config_get_ptr ( ) ;
2017-05-28 17:21:57 +02:00
rarch_system_info_t * sys_info = runloop_get_system_info ( ) ;
2017-02-21 03:44:36 +01:00
2017-04-28 13:43:47 +02:00
content_ctx . check_firmware_before_loading = settings - > bools . check_firmware_before_loading ;
2017-05-14 01:12:47 +02:00
content_ctx . is_ips_pref = rarch_ctl ( RARCH_CTL_IS_IPS_PREF , NULL ) ;
content_ctx . is_bps_pref = rarch_ctl ( RARCH_CTL_IS_BPS_PREF , NULL ) ;
content_ctx . is_ups_pref = rarch_ctl ( RARCH_CTL_IS_UPS_PREF , NULL ) ;
2017-02-21 03:44:36 +01:00
content_ctx . patch_is_blocked = rarch_ctl ( RARCH_CTL_IS_PATCH_BLOCKED , NULL ) ;
2017-05-15 05:06:23 +02:00
content_ctx . bios_is_missing = rarch_ctl ( RARCH_CTL_IS_MISSING_BIOS , NULL ) ;
2017-02-21 03:44:36 +01:00
content_ctx . directory_system = NULL ;
content_ctx . directory_cache = NULL ;
2017-05-14 04:52:34 +02:00
content_ctx . name_ips = NULL ;
content_ctx . name_bps = NULL ;
content_ctx . name_ups = NULL ;
2017-02-21 03:44:36 +01:00
content_ctx . valid_extensions = NULL ;
content_ctx . block_extract = false ;
content_ctx . need_fullpath = false ;
content_ctx . set_supports_no_game_enable = false ;
content_ctx . subsystem . data = NULL ;
content_ctx . subsystem . size = 0 ;
2017-04-28 13:43:47 +02:00
content_ctx . history_list_enable = settings - > bools . history_list_enable ;
2017-02-21 03:44:36 +01:00
2017-05-14 05:00:24 +02:00
if ( global )
{
if ( ! string_is_empty ( global - > name . ips ) )
content_ctx . name_ips = strdup ( global - > name . ips ) ;
if ( ! string_is_empty ( global - > name . bps ) )
content_ctx . name_bps = strdup ( global - > name . bps ) ;
if ( ! string_is_empty ( global - > name . ups ) )
content_ctx . name_ups = strdup ( global - > name . ups ) ;
2017-11-08 19:41:13 -08:00
if ( label )
strlcpy ( global - > name . label , label , sizeof ( global - > name . label ) ) ;
else
global - > name . label [ 0 ] = ' \0 ' ;
2017-05-14 05:00:24 +02:00
}
2017-04-29 00:39:29 +02:00
if ( ! string_is_empty ( settings - > paths . directory_system ) )
content_ctx . directory_system = strdup ( settings - > paths . directory_system ) ;
2017-02-21 03:44:36 +01:00
/* Set libretro core path */
2017-05-15 05:06:23 +02:00
rarch_ctl ( RARCH_CTL_SET_LIBRETRO_PATH , ( void * ) core_path ) ;
2017-02-21 03:44:36 +01:00
/* Is content required by this core? */
if ( fullpath )
2017-05-28 17:21:57 +02:00
sys_info - > load_no_content = false ;
2017-02-21 03:44:36 +01:00
else
2017-05-28 17:21:57 +02:00
sys_info - > load_no_content = true ;
2017-02-21 03:44:36 +01:00
/* On targets that have no dynamic core loading support, we'd
* execute the new core from this point . If this returns false ,
* we assume we can dynamically load the core . */
2018-02-05 16:42:02 +01:00
if ( ! command_event_cmd_exec ( fullpath , & content_ctx , CONTENT_MODE_LOAD_NONE , & error_string ) )
2017-05-14 04:50:57 +02:00
{
if ( error_string )
{
runloop_msg_queue_push ( error_string , 2 , 90 , true ) ;
2017-11-26 00:57:02 +01:00
RARCH_ERR ( " %s \n " , error_string ) ;
2017-05-14 04:50:57 +02:00
free ( error_string ) ;
}
2017-05-15 04:31:40 +02:00
rarch_menu_running ( ) ;
2017-05-14 04:50:57 +02:00
2017-05-14 05:00:24 +02:00
ret = false ;
goto end ;
2017-05-14 04:50:57 +02:00
}
2017-02-21 03:44:36 +01:00
# ifndef HAVE_DYNAMIC
2017-05-15 05:06:23 +02:00
rarch_ctl ( RARCH_CTL_SET_SHUTDOWN , NULL ) ;
2017-05-15 04:31:40 +02:00
rarch_menu_running_finished ( ) ;
2017-02-21 03:44:36 +01:00
# endif
/* Load core */
# ifdef HAVE_DYNAMIC
command_event ( CMD_EVENT_LOAD_CORE , NULL ) ;
# endif
2017-05-14 05:00:24 +02:00
end :
if ( content_ctx . name_ips )
free ( content_ctx . name_ips ) ;
if ( content_ctx . name_bps )
free ( content_ctx . name_bps ) ;
if ( content_ctx . name_ups )
free ( content_ctx . name_ups ) ;
2017-02-21 03:44:36 +01:00
if ( content_ctx . directory_system )
free ( content_ctx . directory_system ) ;
2017-05-14 05:00:24 +02:00
return ret ;
2017-02-21 03:44:36 +01:00
}
2017-02-21 18:55:11 +01:00
# endif
2017-02-21 03:44:36 +01:00
2017-02-21 16:50:39 +01:00
bool task_push_start_current_core ( content_ctx_info_t * content_info )
2017-02-21 03:54:34 +01:00
{
content_information_ctx_t content_ctx ;
2017-12-11 23:55:31 -08:00
2017-05-14 05:00:24 +02:00
bool ret = true ;
2017-02-21 03:54:34 +01:00
char * error_string = NULL ;
2017-05-14 05:00:24 +02:00
global_t * global = global_get_ptr ( ) ;
2017-02-21 03:54:34 +01:00
settings_t * settings = config_get_ptr ( ) ;
if ( ! content_info )
return false ;
2017-02-21 19:06:08 +01:00
2017-04-28 13:43:47 +02:00
content_ctx . check_firmware_before_loading = settings - > bools . check_firmware_before_loading ;
2017-05-14 01:12:47 +02:00
content_ctx . is_ips_pref = rarch_ctl ( RARCH_CTL_IS_IPS_PREF , NULL ) ;
content_ctx . is_bps_pref = rarch_ctl ( RARCH_CTL_IS_BPS_PREF , NULL ) ;
content_ctx . is_ups_pref = rarch_ctl ( RARCH_CTL_IS_UPS_PREF , NULL ) ;
2017-02-21 03:54:34 +01:00
content_ctx . patch_is_blocked = rarch_ctl ( RARCH_CTL_IS_PATCH_BLOCKED , NULL ) ;
2017-05-15 05:06:23 +02:00
content_ctx . bios_is_missing = rarch_ctl ( RARCH_CTL_IS_MISSING_BIOS , NULL ) ;
2017-02-21 03:54:34 +01:00
content_ctx . directory_system = NULL ;
content_ctx . directory_cache = NULL ;
2017-05-14 04:52:34 +02:00
content_ctx . name_ips = NULL ;
content_ctx . name_bps = NULL ;
content_ctx . name_ups = NULL ;
2017-02-21 03:54:34 +01:00
content_ctx . valid_extensions = NULL ;
content_ctx . block_extract = false ;
content_ctx . need_fullpath = false ;
content_ctx . set_supports_no_game_enable = false ;
content_ctx . subsystem . data = NULL ;
content_ctx . subsystem . size = 0 ;
2017-04-28 13:43:47 +02:00
content_ctx . history_list_enable = settings - > bools . history_list_enable ;
2017-02-21 03:54:34 +01:00
2017-05-14 05:00:24 +02:00
if ( global )
{
if ( ! string_is_empty ( global - > name . ips ) )
content_ctx . name_ips = strdup ( global - > name . ips ) ;
if ( ! string_is_empty ( global - > name . bps ) )
content_ctx . name_bps = strdup ( global - > name . bps ) ;
if ( ! string_is_empty ( global - > name . ups ) )
content_ctx . name_ups = strdup ( global - > name . ups ) ;
}
2017-04-29 00:39:29 +02:00
if ( ! string_is_empty ( settings - > paths . directory_system ) )
content_ctx . directory_system = strdup ( settings - > paths . directory_system ) ;
2017-02-21 03:54:34 +01:00
# ifdef HAVE_MENU
if ( ! content_info - > environ_get )
content_info - > environ_get = menu_content_environment_get ;
# endif
/* Clear content path */
path_clear ( RARCH_PATH_CONTENT ) ;
/* Preliminary stuff that has to be done before we
* load the actual content . Can differ per mode . */
retroarch_set_current_core_type ( CORE_TYPE_PLAIN , true ) ;
/* Load content */
2017-02-21 18:58:03 +01:00
if ( firmware_update_status ( & content_ctx ) )
2017-10-11 22:49:13 +02:00
goto end ;
2017-02-21 03:54:34 +01:00
if ( ! task_load_content ( content_info , & content_ctx ,
2017-02-21 05:31:34 +01:00
true , false , & error_string ) )
2017-05-14 04:50:57 +02:00
{
if ( error_string )
{
runloop_msg_queue_push ( error_string , 2 , 90 , true ) ;
2017-11-26 00:57:02 +01:00
RARCH_ERR ( " %s \n " , error_string ) ;
2017-05-14 04:50:57 +02:00
free ( error_string ) ;
}
2017-02-21 03:54:34 +01:00
2017-05-15 04:31:40 +02:00
rarch_menu_running ( ) ;
2017-02-21 03:54:34 +01:00
2017-05-14 05:00:24 +02:00
ret = false ;
goto end ;
2017-02-21 03:54:34 +01:00
}
# ifdef HAVE_MENU
2017-05-14 04:50:57 +02:00
/* Push quick menu onto menu stack */
menu_driver_ctl ( RARCH_MENU_CTL_SET_PENDING_QUICK_MENU , NULL ) ;
2017-02-21 03:54:34 +01:00
# endif
2017-05-14 05:00:24 +02:00
end :
if ( content_ctx . name_ips )
free ( content_ctx . name_ips ) ;
if ( content_ctx . name_bps )
free ( content_ctx . name_bps ) ;
if ( content_ctx . name_ups )
free ( content_ctx . name_ups ) ;
2017-02-21 03:54:34 +01:00
if ( content_ctx . directory_system )
free ( content_ctx . directory_system ) ;
2017-05-14 05:00:24 +02:00
return ret ;
2017-02-21 03:54:34 +01:00
}
2017-02-21 16:53:02 +01:00
bool task_push_load_new_core (
2017-02-21 04:07:40 +01:00
const char * core_path ,
const char * fullpath ,
content_ctx_info_t * content_info ,
enum rarch_core_type type ,
retro_task_callback_t cb ,
void * user_data )
{
/* Set libretro core path */
2017-05-15 05:06:23 +02:00
rarch_ctl ( RARCH_CTL_SET_LIBRETRO_PATH , ( void * ) core_path ) ;
2017-02-21 04:07:40 +01:00
/* Load core */
command_event ( CMD_EVENT_LOAD_CORE , NULL ) ;
# ifndef HAVE_DYNAMIC
/* Fork core? */
if ( ! frontend_driver_set_fork ( FRONTEND_FORK_CORE ) )
return false ;
# endif
/* Preliminary stuff that has to be done before we
* load the actual content . Can differ per mode . */
retroarch_set_current_core_type ( type , true ) ;
return true ;
}
2017-02-21 18:55:11 +01:00
# ifdef HAVE_MENU
2017-02-21 18:36:38 +01:00
bool task_push_load_content_with_new_core_from_menu (
2017-02-21 04:31:03 +01:00
const char * core_path ,
const char * fullpath ,
content_ctx_info_t * content_info ,
enum rarch_core_type type ,
retro_task_callback_t cb ,
void * user_data )
{
content_information_ctx_t content_ctx ;
2017-12-11 23:55:31 -08:00
2017-05-14 05:00:24 +02:00
bool ret = true ;
2017-02-21 04:31:03 +01:00
char * error_string = NULL ;
2017-05-14 05:00:24 +02:00
global_t * global = global_get_ptr ( ) ;
2017-02-21 04:31:03 +01:00
settings_t * settings = config_get_ptr ( ) ;
2017-04-28 13:43:47 +02:00
content_ctx . check_firmware_before_loading = settings - > bools . check_firmware_before_loading ;
2017-05-14 01:12:47 +02:00
content_ctx . is_ips_pref = rarch_ctl ( RARCH_CTL_IS_IPS_PREF , NULL ) ;
content_ctx . is_bps_pref = rarch_ctl ( RARCH_CTL_IS_BPS_PREF , NULL ) ;
content_ctx . is_ups_pref = rarch_ctl ( RARCH_CTL_IS_UPS_PREF , NULL ) ;
2017-02-21 04:31:03 +01:00
content_ctx . patch_is_blocked = rarch_ctl ( RARCH_CTL_IS_PATCH_BLOCKED , NULL ) ;
2017-05-15 05:06:23 +02:00
content_ctx . bios_is_missing = rarch_ctl ( RARCH_CTL_IS_MISSING_BIOS , NULL ) ;
2017-02-21 04:31:03 +01:00
content_ctx . directory_system = NULL ;
content_ctx . directory_cache = NULL ;
2017-05-14 04:52:34 +02:00
content_ctx . name_ips = NULL ;
content_ctx . name_bps = NULL ;
content_ctx . name_ups = NULL ;
2017-02-21 04:31:03 +01:00
content_ctx . valid_extensions = NULL ;
content_ctx . block_extract = false ;
content_ctx . need_fullpath = false ;
content_ctx . set_supports_no_game_enable = false ;
content_ctx . subsystem . data = NULL ;
content_ctx . subsystem . size = 0 ;
2017-04-28 13:43:47 +02:00
content_ctx . history_list_enable = settings - > bools . history_list_enable ;
2017-02-21 04:31:03 +01:00
2017-05-14 05:00:24 +02:00
if ( global )
{
if ( ! string_is_empty ( global - > name . ips ) )
content_ctx . name_ips = strdup ( global - > name . ips ) ;
if ( ! string_is_empty ( global - > name . bps ) )
content_ctx . name_bps = strdup ( global - > name . bps ) ;
if ( ! string_is_empty ( global - > name . ups ) )
content_ctx . name_ups = strdup ( global - > name . ups ) ;
}
2017-04-29 00:39:29 +02:00
if ( ! string_is_empty ( settings - > paths . directory_system ) )
content_ctx . directory_system = strdup ( settings - > paths . directory_system ) ;
2017-02-21 04:31:03 +01:00
/* Set content path */
path_set ( RARCH_PATH_CONTENT , fullpath ) ;
/* Set libretro core path */
2017-05-15 05:06:23 +02:00
rarch_ctl ( RARCH_CTL_SET_LIBRETRO_PATH , ( void * ) core_path ) ;
2017-02-21 04:31:03 +01:00
# ifdef HAVE_DYNAMIC
2017-02-21 05:07:53 +01:00
/* Load core */
2017-02-21 04:31:03 +01:00
command_event ( CMD_EVENT_LOAD_CORE , NULL ) ;
/* Load content */
if ( ! content_info - > environ_get )
content_info - > environ_get = menu_content_environment_get ;
2017-02-21 05:07:53 +01:00
2017-02-21 18:58:03 +01:00
if ( firmware_update_status ( & content_ctx ) )
2017-10-11 22:49:13 +02:00
goto end ;
2017-02-21 04:31:03 +01:00
if ( ! task_load_content ( content_info , & content_ctx ,
2017-02-21 18:55:11 +01:00
true , false , & error_string ) )
2017-02-21 04:31:03 +01:00
{
if ( error_string )
{
runloop_msg_queue_push ( error_string , 2 , 90 , true ) ;
2017-11-26 00:57:02 +01:00
RARCH_ERR ( " %s \n " , error_string ) ;
2017-02-21 04:31:03 +01:00
free ( error_string ) ;
}
2017-05-15 04:31:40 +02:00
rarch_menu_running ( ) ;
2017-02-21 04:31:03 +01:00
2017-05-14 05:00:24 +02:00
ret = false ;
goto end ;
2017-02-21 04:31:03 +01:00
}
# else
2017-12-11 23:55:31 -08:00
command_event_cmd_exec ( path_get ( RARCH_PATH_CONTENT ) , & content_ctx ,
2018-02-05 16:42:02 +01:00
false , & error_string ) ;
2017-02-21 04:31:03 +01:00
command_event ( CMD_EVENT_QUIT , NULL ) ;
# endif
/* Push quick menu onto menu stack */
if ( type ! = CORE_TYPE_DUMMY )
menu_driver_ctl ( RARCH_MENU_CTL_SET_PENDING_QUICK_MENU , NULL ) ;
2017-05-28 18:33:44 +02:00
# ifdef HAVE_DYNAMIC
2017-05-14 05:00:24 +02:00
end :
2017-05-28 18:33:44 +02:00
# endif
2017-05-14 05:00:24 +02:00
if ( content_ctx . name_ips )
free ( content_ctx . name_ips ) ;
if ( content_ctx . name_bps )
free ( content_ctx . name_bps ) ;
if ( content_ctx . name_ups )
free ( content_ctx . name_ups ) ;
2017-02-21 04:31:03 +01:00
if ( content_ctx . directory_system )
free ( content_ctx . directory_system ) ;
2017-05-14 05:00:24 +02:00
return ret ;
2017-02-21 04:31:03 +01:00
}
2017-02-21 18:55:11 +01:00
# endif
2017-02-21 04:31:03 +01:00
2017-02-21 05:31:34 +01:00
static bool task_load_content_callback ( content_ctx_info_t * content_info ,
bool loading_from_menu , bool loading_from_cli )
2017-02-21 05:17:07 +01:00
{
content_information_ctx_t content_ctx ;
bool ret = false ;
char * error_string = NULL ;
2017-05-14 05:00:24 +02:00
global_t * global = global_get_ptr ( ) ;
2017-02-21 05:17:07 +01:00
settings_t * settings = config_get_ptr ( ) ;
2017-04-28 13:43:47 +02:00
content_ctx . check_firmware_before_loading = settings - > bools . check_firmware_before_loading ;
2017-05-14 01:12:47 +02:00
content_ctx . is_ips_pref = rarch_ctl ( RARCH_CTL_IS_IPS_PREF , NULL ) ;
content_ctx . is_bps_pref = rarch_ctl ( RARCH_CTL_IS_BPS_PREF , NULL ) ;
content_ctx . is_ups_pref = rarch_ctl ( RARCH_CTL_IS_UPS_PREF , NULL ) ;
2017-02-21 05:17:07 +01:00
content_ctx . patch_is_blocked = rarch_ctl ( RARCH_CTL_IS_PATCH_BLOCKED , NULL ) ;
2017-05-15 05:06:23 +02:00
content_ctx . bios_is_missing = rarch_ctl ( RARCH_CTL_IS_MISSING_BIOS , NULL ) ;
2017-02-21 05:17:07 +01:00
content_ctx . directory_system = NULL ;
content_ctx . directory_cache = NULL ;
2017-05-14 04:52:34 +02:00
content_ctx . name_ips = NULL ;
content_ctx . name_bps = NULL ;
content_ctx . name_ups = NULL ;
2017-02-21 05:17:07 +01:00
content_ctx . valid_extensions = NULL ;
content_ctx . block_extract = false ;
content_ctx . need_fullpath = false ;
content_ctx . set_supports_no_game_enable = false ;
content_ctx . subsystem . data = NULL ;
content_ctx . subsystem . size = 0 ;
2017-04-28 13:43:47 +02:00
content_ctx . history_list_enable = settings - > bools . history_list_enable ;
2017-02-21 05:17:07 +01:00
2017-05-14 05:00:24 +02:00
if ( global )
{
if ( ! string_is_empty ( global - > name . ips ) )
content_ctx . name_ips = strdup ( global - > name . ips ) ;
if ( ! string_is_empty ( global - > name . bps ) )
content_ctx . name_bps = strdup ( global - > name . bps ) ;
if ( ! string_is_empty ( global - > name . ups ) )
content_ctx . name_ups = strdup ( global - > name . ups ) ;
}
2017-04-29 00:39:29 +02:00
if ( ! string_is_empty ( settings - > paths . directory_system ) )
content_ctx . directory_system = strdup ( settings - > paths . directory_system ) ;
2017-02-21 05:17:07 +01:00
# ifdef HAVE_MENU
if ( ! content_info - > environ_get )
content_info - > environ_get = menu_content_environment_get ;
# endif
2017-02-21 18:58:03 +01:00
if ( firmware_update_status ( & content_ctx ) )
2017-10-11 22:49:13 +02:00
goto end ;
2017-02-21 05:17:07 +01:00
2017-02-21 05:31:34 +01:00
ret = task_load_content ( content_info , & content_ctx , true , loading_from_cli , & error_string ) ;
2017-02-21 05:17:07 +01:00
2017-10-11 22:49:13 +02:00
end :
2017-05-14 05:00:24 +02:00
if ( content_ctx . name_ips )
free ( content_ctx . name_ips ) ;
if ( content_ctx . name_bps )
free ( content_ctx . name_bps ) ;
if ( content_ctx . name_ups )
free ( content_ctx . name_ups ) ;
2017-02-21 05:17:07 +01:00
if ( content_ctx . directory_system )
free ( content_ctx . directory_system ) ;
if ( ! ret )
{
if ( error_string )
{
runloop_msg_queue_push ( error_string , 2 , 90 , true ) ;
2017-11-26 00:57:02 +01:00
RARCH_ERR ( " %s \n " , error_string ) ;
2017-02-21 05:17:07 +01:00
free ( error_string ) ;
}
return false ;
}
return true ;
}
2017-02-21 18:58:03 +01:00
bool task_push_load_content_with_new_core_from_companion_ui (
2017-02-21 16:30:47 +01:00
const char * core_path ,
const char * fullpath ,
content_ctx_info_t * content_info ,
retro_task_callback_t cb ,
void * user_data )
{
/* Set content path */
path_set ( RARCH_PATH_CONTENT , fullpath ) ;
/* Set libretro core path */
2017-05-15 05:06:23 +02:00
rarch_ctl ( RARCH_CTL_SET_LIBRETRO_PATH , ( void * ) core_path ) ;
2017-02-21 16:30:47 +01:00
# ifdef HAVE_DYNAMIC
command_event ( CMD_EVENT_LOAD_CORE , NULL ) ;
# endif
/* Load content */
if ( ! task_load_content_callback ( content_info , true , false ) )
return false ;
# ifdef HAVE_MENU
2017-10-22 07:35:17 -07:00
/* Push quick menu onto menu stack */
2017-02-21 16:30:47 +01:00
menu_driver_ctl ( RARCH_MENU_CTL_SET_PENDING_QUICK_MENU , NULL ) ;
# endif
return true ;
}
2017-02-21 16:59:48 +01:00
bool task_push_load_content_from_cli (
const char * core_path ,
const char * fullpath ,
content_ctx_info_t * content_info ,
enum rarch_core_type type ,
retro_task_callback_t cb ,
void * user_data )
{
/* Load content */
if ( ! task_load_content_callback ( content_info , true , true ) )
return false ;
return true ;
}
2017-02-21 17:22:04 +01:00
bool task_push_start_builtin_core (
2016-05-16 16:25:16 +02:00
content_ctx_info_t * content_info ,
2016-05-16 14:20:26 +02:00
enum rarch_core_type type ,
retro_task_callback_t cb ,
void * user_data )
2016-01-24 00:40:34 +01:00
{
2016-06-03 19:02:19 +02:00
/* Clear content path */
2017-02-21 17:22:04 +01:00
path_clear ( RARCH_PATH_CONTENT ) ;
/* Preliminary stuff that has to be done before we
* load the actual content . Can differ per mode . */
retroarch_set_current_core_type ( type , true ) ;
/* Load content */
if ( ! task_load_content_callback ( content_info , true , false ) )
2016-05-29 00:03:15 +02:00
{
2017-05-15 04:31:40 +02:00
rarch_menu_running ( ) ;
2017-02-21 17:22:04 +01:00
return false ;
2016-05-29 00:03:15 +02:00
}
2017-02-21 17:22:04 +01:00
/* Push quick menu onto menu stack */
# ifdef HAVE_MENU
menu_driver_ctl ( RARCH_MENU_CTL_SET_PENDING_QUICK_MENU , NULL ) ;
# endif
return true ;
}
2017-02-21 17:29:30 +01:00
bool task_push_load_content_with_current_core_from_companion_ui (
const char * fullpath ,
content_ctx_info_t * content_info ,
enum rarch_core_type type ,
retro_task_callback_t cb ,
void * user_data )
{
/* Set content path */
path_set ( RARCH_PATH_CONTENT , fullpath ) ;
/* Load content */
if ( ! task_load_content_callback ( content_info , true , false ) )
return false ;
/* Push quick menu onto menu stack */
# ifdef HAVE_MENU
if ( type ! = CORE_TYPE_DUMMY )
menu_driver_ctl ( RARCH_MENU_CTL_SET_PENDING_QUICK_MENU , NULL ) ;
# endif
return true ;
}
2017-02-21 18:55:11 +01:00
# ifdef HAVE_MENU
2017-02-21 18:36:38 +01:00
bool task_push_load_content_with_core_from_menu (
2017-02-21 17:22:04 +01:00
const char * fullpath ,
content_ctx_info_t * content_info ,
enum rarch_core_type type ,
retro_task_callback_t cb ,
void * user_data )
{
2016-06-03 18:42:47 +02:00
/* Set content path */
2017-02-21 18:36:38 +01:00
path_set ( RARCH_PATH_CONTENT , fullpath ) ;
2016-05-28 23:56:07 +02:00
2016-06-03 18:59:57 +02:00
/* Load content */
2017-02-21 18:36:38 +01:00
if ( ! task_load_content_callback ( content_info , true , false ) )
2016-06-03 18:59:57 +02:00
{
2017-05-15 04:31:40 +02:00
rarch_menu_running ( ) ;
2017-02-21 18:36:38 +01:00
return false ;
2016-06-03 18:59:57 +02:00
}
2016-05-16 14:54:26 +02:00
2016-06-03 18:59:57 +02:00
/* Push quick menu onto menu stack */
2017-02-21 16:59:48 +01:00
if ( type ! = CORE_TYPE_DUMMY )
2017-02-21 04:07:40 +01:00
menu_driver_ctl ( RARCH_MENU_CTL_SET_PENDING_QUICK_MENU , NULL ) ;
2016-05-16 14:23:13 +02:00
2016-11-29 22:21:44 -05:00
return true ;
2016-01-24 00:40:34 +01:00
}
2017-02-21 18:55:11 +01:00
# endif
2016-12-21 00:32:01 +01:00
2017-01-25 15:51:57 +01:00
void content_get_status (
bool * contentless ,
bool * is_inited )
2016-12-21 00:32:01 +01:00
{
2017-01-25 15:44:21 +01:00
* contentless = core_does_not_need_content ;
2017-01-25 15:51:57 +01:00
* is_inited = _content_is_inited ;
2016-12-21 00:32:01 +01:00
}
2018-02-10 19:08:39 -05:00
/* Clears the pending subsystem rom buffer*/
void content_clear_subsystem ( void )
{
pending_subsystem_rom_id = 0 ;
for ( int i = 0 ; i < RARCH_MAX_SUBSYSTEM_ROMS ; i + + )
pending_subsystem_roms [ i ] [ 0 ] = ' \0 ' ;
}
/* Add a rom to the subsystem rom buffer */
void content_add_subsystem ( const char * path )
{
strlcpy ( pending_subsystem_roms [ pending_subsystem_rom_id ] , path , sizeof ( pending_subsystem_roms [ pending_subsystem_rom_id ] ) ) ;
RARCH_LOG ( " [subsystem] subsystem id: %d rom id: %d, rom path: %s \n " , pending_subsystem , pending_subsystem_rom_id , pending_subsystem_roms [ pending_subsystem_rom_id ] ) ;
pending_subsystem_rom_id + + ;
}
2016-12-21 00:32:01 +01:00
void content_set_does_not_need_content ( void )
{
core_does_not_need_content = true ;
}
void content_unset_does_not_need_content ( void )
{
core_does_not_need_content = false ;
}
2017-05-06 16:41:22 +02:00
uint32_t content_get_crc ( void )
2016-12-21 00:32:01 +01:00
{
2017-05-06 16:41:22 +02:00
return content_rom_crc ;
2016-12-21 00:32:01 +01:00
}
bool content_is_inited ( void )
{
return _content_is_inited ;
}
void content_deinit ( void )
{
unsigned i ;
if ( temporary_content )
{
for ( i = 0 ; i < temporary_content - > size ; i + + )
{
const char * path = temporary_content - > elems [ i ] . data ;
RARCH_LOG ( " %s: %s. \n " ,
msg_hash_to_str ( MSG_REMOVING_TEMPORARY_CONTENT_FILE ) , path ) ;
2017-12-14 13:29:36 -05:00
if ( ! filestream_delete ( path ) )
2016-12-21 00:32:01 +01:00
RARCH_ERR ( " %s: %s. \n " ,
msg_hash_to_str ( MSG_FAILED_TO_REMOVE_TEMPORARY_FILE ) ,
path ) ;
}
string_list_free ( temporary_content ) ;
}
temporary_content = NULL ;
2017-05-06 16:41:22 +02:00
content_rom_crc = 0 ;
2016-12-21 00:32:01 +01:00
_content_is_inited = false ;
core_does_not_need_content = false ;
}
/* Initializes and loads a content file for the currently
* selected libretro core . */
bool content_init ( void )
{
content_information_ctx_t content_ctx ;
2016-12-21 15:21:11 +01:00
bool ret = true ;
char * error_string = NULL ;
2017-05-14 20:23:10 +02:00
struct string_list * content = NULL ;
2017-05-14 05:00:24 +02:00
global_t * global = global_get_ptr ( ) ;
2017-02-21 19:06:08 +01:00
settings_t * settings = config_get_ptr ( ) ;
2017-04-23 16:41:26 +02:00
rarch_system_info_t * sys_info = runloop_get_system_info ( ) ;
2016-12-21 00:32:01 +01:00
2017-02-21 19:56:32 +01:00
temporary_content = string_list_new ( ) ;
2017-04-28 13:43:47 +02:00
content_ctx . check_firmware_before_loading = settings - > bools . check_firmware_before_loading ;
2017-05-14 01:12:47 +02:00
content_ctx . is_ips_pref = rarch_ctl ( RARCH_CTL_IS_IPS_PREF , NULL ) ;
content_ctx . is_bps_pref = rarch_ctl ( RARCH_CTL_IS_BPS_PREF , NULL ) ;
content_ctx . is_ups_pref = rarch_ctl ( RARCH_CTL_IS_UPS_PREF , NULL ) ;
2016-12-21 15:21:11 +01:00
content_ctx . temporary_content = temporary_content ;
2016-12-21 00:32:01 +01:00
content_ctx . history_list_enable = false ;
content_ctx . directory_system = NULL ;
content_ctx . directory_cache = NULL ;
2017-05-14 04:52:34 +02:00
content_ctx . name_ips = NULL ;
content_ctx . name_bps = NULL ;
content_ctx . name_ups = NULL ;
2016-12-21 00:32:01 +01:00
content_ctx . valid_extensions = NULL ;
content_ctx . block_extract = false ;
content_ctx . need_fullpath = false ;
content_ctx . set_supports_no_game_enable = false ;
2017-01-31 03:57:29 +01:00
content_ctx . patch_is_blocked = false ;
2016-12-21 00:32:01 +01:00
content_ctx . subsystem . data = NULL ;
content_ctx . subsystem . size = 0 ;
2017-05-14 05:00:24 +02:00
if ( global )
{
if ( ! string_is_empty ( global - > name . ips ) )
content_ctx . name_ips = strdup ( global - > name . ips ) ;
if ( ! string_is_empty ( global - > name . bps ) )
content_ctx . name_bps = strdup ( global - > name . bps ) ;
if ( ! string_is_empty ( global - > name . ups ) )
content_ctx . name_ups = strdup ( global - > name . ups ) ;
}
2017-12-11 23:55:31 -08:00
2016-12-21 00:32:01 +01:00
if ( sys_info )
{
2017-04-28 13:43:47 +02:00
content_ctx . history_list_enable = settings - > bools . history_list_enable ;
content_ctx . set_supports_no_game_enable = settings - > bools . set_supports_no_game_enable ;
2016-12-22 00:41:36 +01:00
2017-04-29 00:39:29 +02:00
if ( ! string_is_empty ( settings - > paths . directory_system ) )
content_ctx . directory_system = strdup ( settings - > paths . directory_system ) ;
if ( ! string_is_empty ( settings - > paths . directory_cache ) )
content_ctx . directory_cache = strdup ( settings - > paths . directory_cache ) ;
2017-05-30 01:44:49 +02:00
if ( ! string_is_empty ( sys_info - > info . valid_extensions ) )
content_ctx . valid_extensions = strdup ( sys_info - > info . valid_extensions ) ;
2016-12-22 00:42:56 +01:00
2017-05-30 01:44:49 +02:00
content_ctx . block_extract = sys_info - > info . block_extract ;
content_ctx . need_fullpath = sys_info - > info . need_fullpath ;
2016-12-21 00:32:01 +01:00
content_ctx . subsystem . data = sys_info - > subsystem . data ;
content_ctx . subsystem . size = sys_info - > subsystem . size ;
}
2017-05-14 04:50:57 +02:00
_content_is_inited = true ;
2017-05-14 20:23:10 +02:00
content = string_list_new ( ) ;
2017-05-14 04:50:57 +02:00
2017-12-11 23:55:31 -08:00
if ( ! temporary_content
2017-05-14 20:23:10 +02:00
| | ! content_file_init ( & content_ctx , content , & error_string ) )
2016-12-21 00:32:01 +01:00
{
content_deinit ( ) ;
2017-05-14 04:50:57 +02:00
ret = false ;
2016-12-21 00:32:01 +01:00
}
2017-05-14 20:23:10 +02:00
string_list_free ( content ) ;
2017-05-14 05:00:24 +02:00
if ( content_ctx . name_ips )
free ( content_ctx . name_ips ) ;
if ( content_ctx . name_bps )
free ( content_ctx . name_bps ) ;
if ( content_ctx . name_ups )
free ( content_ctx . name_ups ) ;
2016-12-21 00:32:01 +01:00
if ( content_ctx . directory_system )
free ( content_ctx . directory_system ) ;
if ( content_ctx . directory_cache )
free ( content_ctx . directory_cache ) ;
if ( content_ctx . valid_extensions )
free ( content_ctx . valid_extensions ) ;
if ( error_string )
{
if ( ret )
{
RARCH_LOG ( " %s \n " , error_string ) ;
}
else
{
RARCH_ERR ( " %s \n " , error_string ) ;
}
2016-12-22 23:36:11 +01:00
runloop_msg_queue_push ( error_string , 2 , ret ? 1 : 180 , true ) ;
2016-12-21 00:32:01 +01:00
free ( error_string ) ;
}
return ret ;
}