2014-02-07 02:14:02 -05:00
/* RetroArch - A frontend for libretro.
2014-01-01 01:50:59 +01:00
* Copyright ( C ) 2010 - 2014 - Hans - Kristian Arntzen
2017-03-22 03:09:18 +01:00
* Copyright ( C ) 2011 - 2017 - Daniel De Matteis
2014-04-12 13:59:19 +02:00
*
2012-04-21 23:13:50 +02:00
* RetroArch is free software : you can redistribute it and / or modify it under the terms
2010-12-30 13:54:49 +01:00
* 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 .
*
2012-04-21 23:13:50 +02:00
* RetroArch is distributed in the hope that it will be useful , but WITHOUT ANY WARRANTY ;
2010-12-30 13:54:49 +01:00
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE . See the GNU General Public License for more details .
*
2012-04-21 23:31:57 +02:00
* You should have received a copy of the GNU General Public License along with RetroArch .
2010-12-30 13:54:49 +01:00
* If not , see < http : //www.gnu.org/licenses/>.
*/
2016-09-06 01:02:25 +02:00
# include <stdarg.h>
2010-12-30 13:54:49 +01:00
# include <string.h>
2013-03-22 20:56:23 +01:00
# include <ctype.h>
2011-01-07 17:59:53 +01:00
2016-02-05 13:51:30 +01:00
# include <boolean.h>
2015-06-30 00:38:10 +02:00
# include <file/file_path.h>
# include <compat/strl.h>
# include <compat/posix_string.h>
2015-12-05 20:26:37 +01:00
# include <dynamic/dylib.h>
2015-12-26 07:13:43 +01:00
# include <string/stdstring.h>
2016-02-05 13:51:30 +01:00
# include <retro_assert.h>
2017-12-15 00:31:37 +01:00
# include <libretro.h>
2017-12-14 17:27:02 +01:00
# define VFS_FRONTEND
2017-12-14 15:06:28 +01:00
# include <vfs/vfs_implementation.h>
2015-09-15 05:22:57 +02:00
2016-05-10 20:31:27 +02:00
# include <features/features_cpu.h>
2011-01-07 17:59:53 +01:00
# ifdef HAVE_CONFIG_H
2010-12-30 13:54:49 +01:00
# include "config.h"
2011-01-07 17:59:53 +01:00
# endif
2016-09-08 05:48:43 +02:00
# ifdef HAVE_CHEEVOS
2019-05-29 14:26:22 -03:00
# include "cheevos-new/cheevos.h"
2016-09-08 05:48:43 +02:00
# endif
2019-04-24 03:23:57 +02:00
# if defined(HAVE_OPENGL)
2018-10-10 18:24:41 +02:00
# include "gfx/common/gl_common.h"
2019-04-24 03:23:57 +02:00
# elif defined(HAVE_OPENGL_CORE)
# include "gfx/common/gl_core_common.h"
2018-10-10 18:24:41 +02:00
# endif
2016-12-12 13:30:50 +01:00
# ifdef HAVE_NETWORKING
# include "network/netplay/netplay.h"
# endif
2016-03-22 02:56:06 +01:00
# include "dynamic.h"
2016-05-09 20:30:47 +02:00
# include "command.h"
2016-03-22 02:56:06 +01:00
2016-09-11 16:31:23 +02:00
# include "driver.h"
2016-05-10 08:53:14 +02:00
# include "performance_counters.h"
2017-12-27 11:05:12 -05:00
# include "led/led_driver.h"
2018-06-04 07:48:08 +02:00
# include "midi/midi_driver.h"
2015-11-25 03:29:18 +01:00
2015-06-21 00:03:27 +02:00
# include "cores/internal_cores.h"
2016-03-02 06:20:36 +01:00
# include "content.h"
2016-09-17 16:14:25 +02:00
# include "dirs.h"
2016-09-17 12:19:17 +02:00
# include "paths.h"
2015-01-09 17:40:47 +01:00
# include "retroarch.h"
2015-06-02 17:17:46 +02:00
# include "configuration.h"
2015-11-23 12:03:38 +01:00
# include "verbosity.h"
2018-09-08 02:11:18 +02:00
# include "tasks/tasks_internal.h"
2010-12-30 13:54:49 +01:00
2019-05-11 17:24:00 +02:00
# ifdef HAVE_MENU_WIDGETS
# include "menu/widgets/menu_widgets.h"
# endif
2018-03-29 15:38:22 +02:00
# ifdef HAVE_RUNAHEAD
2018-03-28 14:22:07 -05:00
# include "runahead/secondary_core.h"
2018-03-30 20:22:35 -05:00
# include "runahead/run_ahead.h"
2018-03-29 15:38:22 +02:00
# endif
2018-03-28 14:22:07 -05:00
2012-04-05 11:47:43 +02:00
# ifdef HAVE_DYNAMIC
2015-09-15 05:22:57 +02:00
# define SYMBOL(x) do { \
2018-03-28 14:22:07 -05:00
function_t func = dylib_proc ( lib_handle_local , # x ) ; \
2016-01-28 03:41:30 +01:00
memcpy ( & current_core - > x , & func , sizeof ( func ) ) ; \
2016-05-09 07:09:26 +02:00
if ( current_core - > x = = NULL ) { RARCH_ERR ( " Failed to load symbol: \" %s \" \n " , # x ) ; retroarch_fail ( 1 , " init_libretro_sym() " ) ; } \
2011-10-15 12:56:48 +02:00
} while ( 0 )
2010-12-30 13:54:49 +01:00
2013-04-14 16:24:19 +02:00
static dylib_t lib_handle ;
2012-04-05 11:47:43 +02:00
# else
2016-01-28 03:41:30 +01:00
# define SYMBOL(x) current_core->x = x
2011-01-19 13:25:18 +01:00
# endif
2010-12-30 13:54:49 +01:00
2016-01-28 03:41:30 +01:00
# define SYMBOL_DUMMY(x) current_core->x = libretro_dummy_##x
2016-05-26 19:43:15 +02:00
2015-06-21 00:03:27 +02:00
# ifdef HAVE_FFMPEG
2016-01-28 03:41:30 +01:00
# define SYMBOL_FFMPEG(x) current_core->x = libretro_ffmpeg_##x
2015-06-21 00:03:27 +02:00
# endif
2016-05-26 19:43:15 +02:00
2018-06-20 04:29:31 +02:00
# ifdef HAVE_MPV
# define SYMBOL_MPV(x) current_core->x = libretro_mpv_##x
# endif
2015-06-28 18:55:00 +02:00
# ifdef HAVE_IMAGEVIEWER
2016-01-28 03:41:30 +01:00
# define SYMBOL_IMAGEVIEWER(x) current_core->x = libretro_imageviewer_##x
2015-06-28 18:55:00 +02:00
# endif
2015-06-28 17:02:01 +02:00
2016-09-29 21:07:10 +02:00
# if defined(HAVE_NETWORKING) && defined(HAVE_NETWORKGAMEPAD)
2016-05-26 19:43:15 +02:00
# define SYMBOL_NETRETROPAD(x) current_core->x = libretro_netretropad_##x
# endif
2019-01-30 11:51:21 -08:00
# if defined(HAVE_VIDEOPROCESSOR)
2016-07-28 19:10:18 +02:00
# define SYMBOL_VIDEOPROCESSOR(x) current_core->x = libretro_videoprocessor_##x
# endif
2019-01-05 18:33:29 -05:00
# ifdef HAVE_EASTEREGG
# define SYMBOL_GONG(x) current_core->x = libretro_gong_##x
# endif
2019-06-14 02:12:29 +02:00
# define CORE_SYMBOLS(x) \
x ( retro_init ) ; \
x ( retro_deinit ) ; \
x ( retro_api_version ) ; \
x ( retro_get_system_info ) ; \
x ( retro_get_system_av_info ) ; \
x ( retro_set_environment ) ; \
x ( retro_set_video_refresh ) ; \
x ( retro_set_audio_sample ) ; \
x ( retro_set_audio_sample_batch ) ; \
x ( retro_set_input_poll ) ; \
x ( retro_set_input_state ) ; \
x ( retro_set_controller_port_device ) ; \
x ( retro_reset ) ; \
x ( retro_run ) ; \
x ( retro_serialize_size ) ; \
x ( retro_serialize ) ; \
x ( retro_unserialize ) ; \
x ( retro_cheat_reset ) ; \
x ( retro_cheat_set ) ; \
x ( retro_load_game ) ; \
x ( retro_load_game_special ) ; \
x ( retro_unload_game ) ; \
x ( retro_get_region ) ; \
x ( retro_get_memory_data ) ; \
x ( retro_get_memory_size ) ;
2017-08-07 18:05:43 +02:00
static bool ignore_environment_cb = false ;
static bool core_set_shared_context = false ;
static bool * load_no_content_hook = NULL ;
2014-09-23 03:07:33 +02:00
2019-01-12 21:34:14 +01:00
struct retro_subsystem_info subsystem_data [ SUBSYSTEM_MAX_SUBSYSTEMS ] ;
struct retro_subsystem_rom_info subsystem_data_roms [ SUBSYSTEM_MAX_SUBSYSTEMS ] [ SUBSYSTEM_MAX_SUBSYSTEM_ROMS ] ;
unsigned subsystem_current_count ;
2016-01-25 07:02:26 +01:00
const struct retro_subsystem_info * libretro_find_subsystem_info (
const struct retro_subsystem_info * info , unsigned num_info ,
const char * ident )
{
unsigned i ;
for ( i = 0 ; i < num_info ; i + + )
{
if ( string_is_equal ( info [ i ] . ident , ident ) )
return & info [ i ] ;
else if ( string_is_equal ( info [ i ] . desc , ident ) )
return & info [ i ] ;
}
return NULL ;
}
/**
* libretro_find_controller_description :
* @ info : Pointer to controller info handle .
* @ id : Identifier of controller to search
* for .
*
* Search for a controller of type @ id in @ info .
*
* Returns : controller description of found controller on success ,
* otherwise NULL .
* */
const struct retro_controller_description *
libretro_find_controller_description (
const struct retro_controller_info * info , unsigned id )
{
unsigned i ;
for ( i = 0 ; i < info - > num_types ; i + + )
{
if ( info - > types [ i ] . id ! = id )
continue ;
return & info - > types [ i ] ;
}
return NULL ;
}
2016-03-21 22:57:19 +01:00
/**
* libretro_free_system_info :
* @ info : Pointer to system info information .
*
* Frees system information .
* */
2017-05-30 01:44:49 +02:00
void libretro_free_system_info ( struct retro_system_info * info )
2016-03-21 22:57:19 +01:00
{
2017-05-29 03:24:15 +02:00
if ( ! info )
return ;
2017-05-30 01:44:49 +02:00
free ( ( void * ) info - > library_name ) ;
free ( ( void * ) info - > library_version ) ;
free ( ( void * ) info - > valid_extensions ) ;
2017-05-29 03:24:15 +02:00
memset ( info , 0 , sizeof ( * info ) ) ;
2016-03-21 22:57:19 +01:00
}
2013-05-02 14:42:58 +02:00
static bool environ_cb_get_system_info ( unsigned cmd , void * data )
{
2018-10-29 21:23:53 -05:00
rarch_system_info_t * system = runloop_get_system_info ( ) ;
2013-05-02 14:42:58 +02:00
switch ( cmd )
{
case RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME :
2014-07-28 19:37:25 +02:00
* load_no_content_hook = * ( const bool * ) data ;
2013-05-02 14:42:58 +02:00
break ;
2018-10-29 21:23:53 -05:00
case RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO :
{
2019-01-20 02:37:05 +01:00
unsigned i , j , size ;
2018-10-29 21:23:53 -05:00
const struct retro_subsystem_info * info =
( const struct retro_subsystem_info * ) data ;
2019-04-28 01:55:49 +02:00
settings_t * settings = config_get_ptr ( ) ;
unsigned log_level = settings - > uints . libretro_log_level ;
2018-12-10 21:38:30 -05:00
subsystem_current_count = 0 ;
2019-04-28 01:55:49 +02:00
2019-04-28 02:03:56 +02:00
RARCH_LOG ( " Environ SET_SUBSYSTEM_INFO. \n " ) ;
2018-10-29 21:23:53 -05:00
for ( i = 0 ; info [ i ] . ident ; i + + )
{
2019-04-28 01:55:49 +02:00
if ( log_level ! = RETRO_LOG_DEBUG )
continue ;
2018-10-29 21:23:53 -05:00
RARCH_LOG ( " Subsystem ID: %d \n " , i ) ;
RARCH_LOG ( " Special game type: %s \n " , info [ i ] . desc ) ;
RARCH_LOG ( " Ident: %s \n " , info [ i ] . ident ) ;
RARCH_LOG ( " ID: %u \n " , info [ i ] . id ) ;
RARCH_LOG ( " Content: \n " ) ;
for ( j = 0 ; j < info [ i ] . num_roms ; j + + )
{
RARCH_LOG ( " %s (%s) \n " ,
info [ i ] . roms [ j ] . desc , info [ i ] . roms [ j ] . required ?
" required " : " optional " ) ;
}
}
2019-04-28 02:03:56 +02:00
if ( log_level = = RETRO_LOG_DEBUG )
RARCH_LOG ( " Subsystems: %d \n " , i ) ;
2018-12-10 21:38:30 -05:00
size = i ;
2019-04-28 01:55:49 +02:00
if ( log_level = = RETRO_LOG_DEBUG )
if ( size > SUBSYSTEM_MAX_SUBSYSTEMS )
RARCH_WARN ( " Subsystems exceed subsystem max, clamping to %d \n " , SUBSYSTEM_MAX_SUBSYSTEMS ) ;
2018-10-29 21:23:53 -05:00
if ( system )
{
2018-12-10 21:38:30 -05:00
for ( i = 0 ; i < size & & i < SUBSYSTEM_MAX_SUBSYSTEMS ; i + + )
2018-10-29 21:23:53 -05:00
{
2019-02-06 14:22:21 +00:00
/* Nasty, but have to do it like this since
* the pointers are const char *
* ( if we don ' t free them , we get a memory leak ) */
if ( ! string_is_empty ( subsystem_data [ i ] . desc ) )
free ( ( char * ) subsystem_data [ i ] . desc ) ;
if ( ! string_is_empty ( subsystem_data [ i ] . ident ) )
free ( ( char * ) subsystem_data [ i ] . ident ) ;
2018-10-29 21:23:53 -05:00
subsystem_data [ i ] . desc = strdup ( info [ i ] . desc ) ;
subsystem_data [ i ] . ident = strdup ( info [ i ] . ident ) ;
subsystem_data [ i ] . id = info [ i ] . id ;
subsystem_data [ i ] . num_roms = info [ i ] . num_roms ;
2019-04-28 01:55:49 +02:00
if ( log_level = = RETRO_LOG_DEBUG )
if ( subsystem_data [ i ] . num_roms > SUBSYSTEM_MAX_SUBSYSTEM_ROMS )
RARCH_WARN ( " Subsystems exceed subsystem max roms, clamping to %d \n " , SUBSYSTEM_MAX_SUBSYSTEM_ROMS ) ;
2018-12-10 21:38:30 -05:00
for ( j = 0 ; j < subsystem_data [ i ] . num_roms & & j < SUBSYSTEM_MAX_SUBSYSTEM_ROMS ; j + + )
2018-10-29 21:23:53 -05:00
{
2019-02-06 14:22:21 +00:00
/* Nasty, but have to do it like this since
* the pointers are const char *
* ( if we don ' t free them , we get a memory leak ) */
if ( ! string_is_empty ( subsystem_data_roms [ i ] [ j ] . desc ) )
free ( ( char * ) subsystem_data_roms [ i ] [ j ] . desc ) ;
if ( ! string_is_empty ( subsystem_data_roms [ i ] [ j ] . valid_extensions ) )
free ( ( char * ) subsystem_data_roms [ i ] [ j ] . valid_extensions ) ;
2018-10-29 21:23:53 -05:00
subsystem_data_roms [ i ] [ j ] . desc = strdup ( info [ i ] . roms [ j ] . desc ) ;
subsystem_data_roms [ i ] [ j ] . valid_extensions = strdup ( info [ i ] . roms [ j ] . valid_extensions ) ;
subsystem_data_roms [ i ] [ j ] . required = info [ i ] . roms [ j ] . required ;
subsystem_data_roms [ i ] [ j ] . block_extract = info [ i ] . roms [ j ] . block_extract ;
subsystem_data_roms [ i ] [ j ] . need_fullpath = info [ i ] . roms [ j ] . need_fullpath ;
}
subsystem_data [ i ] . roms = subsystem_data_roms [ i ] ;
}
2019-04-28 01:55:49 +02:00
subsystem_current_count =
size < = SUBSYSTEM_MAX_SUBSYSTEMS
? size
: SUBSYSTEM_MAX_SUBSYSTEMS ;
2018-10-29 21:23:53 -05:00
}
break ;
}
2013-05-02 14:42:58 +02:00
default :
return false ;
}
return true ;
}
2016-09-12 19:58:05 +02:00
# ifdef HAVE_DYNAMIC
2016-09-17 01:45:24 +02:00
/**
* libretro_get_environment_info :
* @ func : Function pointer for get_environment_info .
* @ load_no_content : If true , core should be able to auto - start
* without any content loaded .
*
* Sets environment callback in order to get statically known
* information from it .
*
* Fetched via environment callbacks instead of
* retro_get_system_info ( ) , as this info is part of extensions .
*
* Should only be called once right after core load to
* avoid overwriting the " real " environ callback .
*
* For statically linked cores , pass retro_set_environment as argument .
*/
2017-04-16 09:42:17 +02:00
static void libretro_get_environment_info ( void ( * func ) ( retro_environment_t ) ,
2016-09-17 01:45:24 +02:00
bool * load_no_content )
{
load_no_content_hook = load_no_content ;
/* load_no_content gets set in this callback. */
func ( environ_cb_get_system_info ) ;
2017-12-11 23:55:31 -08:00
/* It's possible that we just set get_system_info callback
2016-09-17 01:45:24 +02:00
* to the currently running core .
*
* Make sure we reset it to the actual environment callback .
2017-12-11 23:55:31 -08:00
* Ignore any environment callbacks here in case we ' re running
2016-09-17 01:45:24 +02:00
* on the non - current core . */
ignore_environment_cb = true ;
func ( rarch_environment_cb ) ;
ignore_environment_cb = false ;
}
2019-05-29 15:41:56 +02:00
static bool load_dynamic_core ( const char * path , char * buf , size_t size )
2016-09-17 01:45:24 +02:00
{
2019-01-02 13:30:58 +01:00
/* Can't lookup symbols in itself on UWP */
2019-05-29 15:41:56 +02:00
# if !(defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
if ( dylib_proc ( NULL , " retro_init " ) )
2016-09-17 01:45:24 +02:00
{
/* Try to verify that -lretro was not linked in from other modules
* since loading it dynamically and with - l will fail hard . */
RARCH_ERR ( " Serious problem. RetroArch wants to load libretro cores "
2016-11-30 05:00:04 +01:00
" dynamically, but it is already linked. \n " ) ;
2016-09-17 01:45:24 +02:00
RARCH_ERR ( " This could happen if other modules RetroArch depends on "
" link against libretro directly. \n " ) ;
RARCH_ERR ( " Proceeding could cause a crash. Aborting ... \n " ) ;
retroarch_fail ( 1 , " init_libretro_sym() " ) ;
}
2018-12-28 12:41:38 +01:00
# endif
2016-09-17 01:45:24 +02:00
/* Need to use absolute path for this setting. It can be
* saved to content history , and a relative path would
* break in that scenario . */
2019-05-29 15:41:56 +02:00
path_resolve_realpath ( buf , size ) ;
if ( ( lib_handle = dylib_load ( path ) ) )
2016-12-15 12:11:21 +01:00
return true ;
return false ;
2016-09-17 01:45:24 +02:00
}
2016-09-12 19:58:05 +02:00
static dylib_t libretro_get_system_info_lib ( const char * path ,
struct retro_system_info * info , bool * load_no_content )
{
dylib_t lib = dylib_load ( path ) ;
void ( * proc ) ( struct retro_system_info * ) ;
if ( ! lib )
return NULL ;
proc = ( void ( * ) ( struct retro_system_info * ) )
dylib_proc ( lib , " retro_get_system_info " ) ;
if ( ! proc )
{
dylib_close ( lib ) ;
return NULL ;
}
proc ( info ) ;
if ( load_no_content )
{
void ( * set_environ ) ( retro_environment_t ) ;
* load_no_content = false ;
set_environ = ( void ( * ) ( retro_environment_t ) )
dylib_proc ( lib , " retro_set_environment " ) ;
2019-05-29 16:27:06 +02:00
if ( set_environ )
libretro_get_environment_info ( set_environ , load_no_content ) ;
2016-09-12 19:58:05 +02:00
}
return lib ;
}
2016-03-21 22:57:19 +01:00
# endif
2018-10-30 18:24:37 +01:00
static char current_library_name [ 1024 ] ;
static char current_library_version [ 1024 ] ;
static char current_valid_extensions [ 1024 ] ;
2016-09-12 19:56:50 +02:00
/**
* libretro_get_system_info :
* @ path : Path to libretro library .
* @ info : Pointer to system info information .
* @ load_no_content : If true , core should be able to auto - start
* without any content loaded .
*
* Gets system info from an arbitrary lib .
* The struct returned must be freed as strings are allocated dynamically .
*
* Returns : true ( 1 ) if successful , otherwise false ( 0 ) .
* */
bool libretro_get_system_info ( const char * path ,
2017-05-30 01:44:49 +02:00
struct retro_system_info * info , bool * load_no_content )
2016-09-12 19:56:50 +02:00
{
2017-05-29 03:24:15 +02:00
struct retro_system_info dummy_info ;
2016-09-12 19:56:50 +02:00
# ifdef HAVE_DYNAMIC
2017-05-29 03:24:15 +02:00
dylib_t lib ;
# endif
dummy_info . library_name = NULL ;
dummy_info . library_version = NULL ;
dummy_info . valid_extensions = NULL ;
dummy_info . need_fullpath = false ;
dummy_info . block_extract = false ;
# ifdef HAVE_DYNAMIC
lib = libretro_get_system_info_lib (
path , & dummy_info , load_no_content ) ;
2016-12-15 12:11:21 +01:00
2016-09-12 19:56:50 +02:00
if ( ! lib )
2019-05-29 16:27:06 +02:00
{
RARCH_ERR ( " %s: \" %s \" \n " ,
msg_hash_to_str ( MSG_FAILED_TO_OPEN_LIBRETRO_CORE ) ,
path ) ;
RARCH_ERR ( " Error(s): %s \n " , dylib_error ( ) ) ;
2016-09-12 19:56:50 +02:00
return false ;
2019-05-29 16:27:06 +02:00
}
2017-05-28 15:52:07 +02:00
# else
if ( load_no_content )
{
load_no_content_hook = load_no_content ;
/* load_no_content gets set in this callback. */
retro_set_environment ( environ_cb_get_system_info ) ;
2017-12-11 23:55:31 -08:00
/* It's possible that we just set get_system_info callback
2017-05-28 15:52:07 +02:00
* to the currently running core .
*
* Make sure we reset it to the actual environment callback .
2017-12-11 23:55:31 -08:00
* Ignore any environment callbacks here in case we ' re running
2017-05-28 15:52:07 +02:00
* on the non - current core . */
ignore_environment_cb = true ;
retro_set_environment ( rarch_environment_cb ) ;
ignore_environment_cb = false ;
}
2017-05-29 03:24:15 +02:00
retro_get_system_info ( & dummy_info ) ;
# endif
2017-05-30 01:44:49 +02:00
memcpy ( info , & dummy_info , sizeof ( * info ) ) ;
2017-05-29 03:24:15 +02:00
2018-10-30 18:24:37 +01:00
current_library_name [ 0 ] = ' \0 ' ;
current_library_version [ 0 ] = ' \0 ' ;
current_valid_extensions [ 0 ] = ' \0 ' ;
if ( ! string_is_empty ( dummy_info . library_name ) )
2019-02-03 15:49:35 -08:00
strlcpy ( current_library_name ,
2018-10-30 18:24:37 +01:00
dummy_info . library_name , sizeof ( current_library_name ) ) ;
if ( ! string_is_empty ( dummy_info . library_version ) )
2019-02-03 15:49:35 -08:00
strlcpy ( current_library_version ,
2018-10-30 18:24:37 +01:00
dummy_info . library_version , sizeof ( current_library_version ) ) ;
if ( dummy_info . valid_extensions )
2019-02-03 15:49:35 -08:00
strlcpy ( current_valid_extensions ,
2018-10-30 18:24:37 +01:00
dummy_info . valid_extensions , sizeof ( current_valid_extensions ) ) ;
info - > library_name = current_library_name ;
2018-11-04 15:14:08 +01:00
info - > library_version = current_library_version ;
2018-10-30 18:24:37 +01:00
info - > valid_extensions = current_valid_extensions ;
2017-05-29 03:24:15 +02:00
# ifdef HAVE_DYNAMIC
dylib_close ( lib ) ;
2016-09-12 19:56:50 +02:00
# endif
2016-09-12 20:40:07 +02:00
return true ;
2016-09-12 19:56:50 +02:00
}
2015-01-15 02:48:40 +01:00
/**
* load_symbols :
2015-06-20 23:42:30 +02:00
* @ type : Type of core to be loaded .
2015-10-19 19:52:53 -05:00
* If CORE_TYPE_DUMMY , will
2015-06-20 23:42:30 +02:00
* load dummy symbols .
2015-01-15 02:48:40 +01:00
*
2016-10-11 20:28:36 -04:00
* Setup libretro callback symbols . Returns true on success ,
* or false if symbols could not be loaded .
2015-01-15 02:48:40 +01:00
* */
2019-05-29 15:41:56 +02:00
bool init_libretro_sym_custom ( enum rarch_core_type type ,
struct retro_core_t * current_core , const char * lib_path , void * _lib_handle_p )
2010-12-30 13:54:49 +01:00
{
2018-05-12 19:14:49 +02:00
# ifdef HAVE_DYNAMIC
2018-03-28 14:22:07 -05:00
/* the library handle for use with the SYMBOL macro */
dylib_t lib_handle_local ;
2018-05-12 19:14:49 +02:00
# endif
2015-06-20 23:42:30 +02:00
switch ( type )
2012-10-11 22:31:47 +02:00
{
2015-06-20 23:42:30 +02:00
case CORE_TYPE_PLAIN :
2019-02-14 07:20:44 +01:00
{
2015-06-20 23:42:30 +02:00
# ifdef HAVE_DYNAMIC
2018-03-29 15:38:22 +02:00
# ifdef HAVE_RUNAHEAD
2019-02-14 07:20:44 +01:00
dylib_t * lib_handle_p = ( dylib_t * ) _lib_handle_p ;
if ( ! lib_path | | ! lib_handle_p )
2018-03-29 15:38:22 +02:00
# endif
2019-02-14 07:20:44 +01:00
{
2019-05-29 15:41:56 +02:00
const char * path = path_get ( RARCH_PATH_CORE ) ;
if ( string_is_empty ( path ) )
{
RARCH_ERR ( " Frontend is built for dynamic libretro cores, but "
" path is not set. Cannot continue. \n " ) ;
retroarch_fail ( 1 , " init_libretro_sym() " ) ;
}
RARCH_LOG ( " Loading dynamic libretro core from: \" %s \" \n " ,
path ) ;
if ( ! load_dynamic_core (
path ,
path_get_ptr ( RARCH_PATH_CORE ) ,
path_get_realsize ( RARCH_PATH_CORE )
) )
{
RARCH_ERR ( " Failed to open libretro core: \" %s \" \n " , path ) ;
RARCH_ERR ( " Error(s): %s \n " , dylib_error ( ) ) ;
runloop_msg_queue_push ( msg_hash_to_str ( MSG_FAILED_TO_OPEN_LIBRETRO_CORE ) ,
1 , 180 , true , NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_INFO ) ;
2019-02-14 07:20:44 +01:00
return false ;
2019-05-29 15:41:56 +02:00
}
2019-02-14 07:20:44 +01:00
lib_handle_local = lib_handle ;
}
2018-03-29 15:38:22 +02:00
# ifdef HAVE_RUNAHEAD
2019-02-14 07:20:44 +01:00
else
{
/* for a secondary core, we already have a
* primary library loaded , so we can skip
* some checks and just load the library */
retro_assert ( lib_path ! = NULL & & lib_handle_p ! = NULL ) ;
lib_handle_local = dylib_load ( lib_path ) ;
if ( ! lib_handle_local )
return false ;
* lib_handle_p = lib_handle_local ;
}
2018-03-29 15:38:22 +02:00
# endif
2015-06-20 23:42:30 +02:00
# endif
2012-10-11 22:31:47 +02:00
2019-06-01 22:36:27 +02:00
CORE_SYMBOLS ( SYMBOL ) ;
2019-02-14 07:20:44 +01:00
}
2015-06-20 23:42:30 +02:00
break ;
case CORE_TYPE_DUMMY :
2019-06-01 22:36:27 +02:00
CORE_SYMBOLS ( SYMBOL_DUMMY ) ;
2015-06-20 23:42:30 +02:00
break ;
2015-06-21 00:03:27 +02:00
case CORE_TYPE_FFMPEG :
2016-01-25 07:04:54 +01:00
# ifdef HAVE_FFMPEG
2019-06-01 22:36:27 +02:00
CORE_SYMBOLS ( SYMBOL_FFMPEG ) ;
2018-06-20 04:29:31 +02:00
# endif
break ;
case CORE_TYPE_MPV :
# ifdef HAVE_MPV
2019-06-01 22:36:27 +02:00
CORE_SYMBOLS ( SYMBOL_MPV ) ;
2015-06-21 00:03:27 +02:00
# endif
2016-01-25 07:04:54 +01:00
break ;
2015-06-28 17:02:01 +02:00
case CORE_TYPE_IMAGEVIEWER :
2015-06-28 18:55:00 +02:00
# ifdef HAVE_IMAGEVIEWER
2019-06-01 22:36:27 +02:00
CORE_SYMBOLS ( SYMBOL_IMAGEVIEWER ) ;
2016-05-26 19:43:15 +02:00
# endif
break ;
case CORE_TYPE_NETRETROPAD :
2016-09-29 21:07:10 +02:00
# if defined(HAVE_NETWORKING) && defined(HAVE_NETWORKGAMEPAD)
2019-06-01 22:36:27 +02:00
CORE_SYMBOLS ( SYMBOL_NETRETROPAD ) ;
2016-07-28 19:10:18 +02:00
# endif
break ;
2016-07-28 20:35:05 +02:00
case CORE_TYPE_VIDEO_PROCESSOR :
2019-01-30 11:51:21 -08:00
# if defined(HAVE_VIDEOPROCESSOR)
2019-06-01 22:36:27 +02:00
CORE_SYMBOLS ( SYMBOL_VIDEOPROCESSOR ) ;
2019-01-05 18:33:29 -05:00
# endif
break ;
case CORE_TYPE_GONG :
# ifdef HAVE_EASTEREGG
2019-06-01 22:36:27 +02:00
CORE_SYMBOLS ( SYMBOL_GONG ) ;
2015-06-28 18:55:00 +02:00
# endif
2015-06-28 17:02:01 +02:00
break ;
2013-04-28 04:21:52 +02:00
}
2016-10-11 20:28:36 -04:00
return true ;
2013-04-14 16:24:19 +02:00
}
2015-01-15 02:48:40 +01:00
/**
* init_libretro_sym :
2015-06-20 23:42:30 +02:00
* @ type : Type of core to be loaded .
2015-10-19 19:52:53 -05:00
* If CORE_TYPE_DUMMY , will
2015-06-20 23:42:30 +02:00
* load dummy symbols .
2015-01-15 02:48:40 +01:00
*
* Initializes libretro symbols and
2016-10-11 20:28:36 -04:00
* setups environment callback functions . Returns true on success ,
* or false if symbols could not be loaded .
2015-01-15 02:48:40 +01:00
* */
2016-10-11 20:28:36 -04:00
bool init_libretro_sym ( enum rarch_core_type type , struct retro_core_t * current_core )
2010-12-30 13:54:49 +01:00
{
2019-05-29 15:41:56 +02:00
/* Load symbols */
if ( ! init_libretro_sym_custom ( type , current_core , NULL , NULL ) )
2016-10-11 20:28:36 -04:00
return false ;
2018-03-29 15:38:22 +02:00
# ifdef HAVE_RUNAHEAD
2019-02-03 15:49:35 -08:00
/* remember last core type created, so creating a
2018-03-29 15:38:22 +02:00
* secondary core will know what core type to use . */
2018-03-28 14:22:07 -05:00
set_last_core_type ( type ) ;
2018-03-29 15:38:22 +02:00
# endif
2016-10-11 20:28:36 -04:00
return true ;
2010-12-30 13:54:49 +01:00
}
2017-08-07 18:05:43 +02:00
bool libretro_get_shared_context ( void )
{
return core_set_shared_context ;
}
2015-01-15 02:48:40 +01:00
/**
* uninit_libretro_sym :
*
* Frees libretro core .
*
* Frees all core options ,
* associated state , and
* unbind all libretro callback symbols .
* */
2016-01-28 03:36:14 +01:00
void uninit_libretro_sym ( struct retro_core_t * current_core )
2010-12-30 13:54:49 +01:00
{
2011-12-04 17:54:00 +01:00
# ifdef HAVE_DYNAMIC
2010-12-30 13:54:49 +01:00
if ( lib_handle )
2011-03-07 19:12:14 +01:00
dylib_close ( lib_handle ) ;
2013-04-14 16:24:19 +02:00
lib_handle = NULL ;
2011-03-07 19:12:14 +01:00
# endif
2013-04-22 21:10:17 +02:00
2016-01-28 06:30:12 +01:00
memset ( current_core , 0 , sizeof ( struct retro_core_t ) ) ;
2015-12-07 13:56:33 +01:00
2017-08-07 18:05:43 +02:00
core_set_shared_context = false ;
2017-05-15 05:06:23 +02:00
rarch_ctl ( RARCH_CTL_CORE_OPTIONS_DEINIT , NULL ) ;
rarch_ctl ( RARCH_CTL_SYSTEM_INFO_FREE , NULL ) ;
rarch_ctl ( RARCH_CTL_FRAME_TIME_FREE , NULL ) ;
2019-06-17 11:38:28 +02:00
rarch_ctl ( RARCH_CTL_CAMERA_UNSET_ACTIVE , NULL ) ;
2019-06-17 11:57:46 +02:00
rarch_ctl ( RARCH_CTL_LOCATION_UNSET_ACTIVE , NULL ) ;
2013-12-18 19:10:57 +01:00
2014-09-02 05:57:53 +02:00
/* Performance counters no longer valid. */
2016-05-16 10:00:50 +02:00
performance_counters_clear ( ) ;
2011-03-07 19:12:14 +01:00
}
2014-09-02 05:57:53 +02:00
static void rarch_log_libretro ( enum retro_log_level level ,
const char * fmt , . . . )
2013-12-09 10:32:12 +01:00
{
2015-01-09 21:30:07 +01:00
va_list vp ;
2015-03-20 19:48:23 +01:00
settings_t * settings = config_get_ptr ( ) ;
2017-04-28 21:03:04 +02:00
if ( ( unsigned ) level < settings - > uints . libretro_log_level )
2014-03-01 12:02:48 +01:00
return ;
2018-01-17 06:28:26 +01:00
if ( ! verbosity_is_enabled ( ) )
return ;
2013-12-09 10:32:12 +01:00
va_start ( vp , fmt ) ;
switch ( level )
{
case RETRO_LOG_DEBUG :
2015-12-30 00:57:28 +01:00
RARCH_LOG_V ( " [libretro DEBUG] " , fmt , vp ) ;
2013-12-09 10:32:12 +01:00
break ;
case RETRO_LOG_INFO :
2015-12-30 00:57:28 +01:00
RARCH_LOG_OUTPUT_V ( " [libretro INFO] " , fmt , vp ) ;
2013-12-09 10:32:12 +01:00
break ;
case RETRO_LOG_WARN :
2015-12-30 00:57:28 +01:00
RARCH_WARN_V ( " [libretro WARN] " , fmt , vp ) ;
2013-12-09 10:32:12 +01:00
break ;
case RETRO_LOG_ERROR :
2015-12-30 00:57:28 +01:00
RARCH_ERR_V ( " [libretro ERROR] " , fmt , vp ) ;
2013-12-09 10:32:12 +01:00
break ;
default :
break ;
}
va_end ( vp ) ;
}
2016-05-10 17:39:20 -03:00
static size_t mmap_add_bits_down ( size_t n )
2016-05-10 16:42:13 -03:00
{
2016-05-10 16:47:14 -03:00
n | = n > > 1 ;
n | = n > > 2 ;
n | = n > > 4 ;
n | = n > > 8 ;
n | = n > > 16 ;
2017-12-11 23:55:31 -08:00
2016-05-10 16:42:13 -03:00
/* double shift to avoid warnings on 32bit (it's dead code, but compilers suck) */
2016-05-10 16:47:14 -03:00
if ( sizeof ( size_t ) > 4 )
2016-05-10 16:42:13 -03:00
n | = n > > 16 > > 16 ;
2017-12-11 23:55:31 -08:00
2016-05-10 16:47:14 -03:00
return n ;
2016-05-10 16:42:13 -03:00
}
2016-05-10 17:39:20 -03:00
static size_t mmap_inflate ( size_t addr , size_t mask )
2016-05-10 16:42:13 -03:00
{
2016-05-10 16:47:14 -03:00
while ( mask )
2016-05-10 16:42:13 -03:00
{
size_t tmp = ( mask - 1 ) & ~ mask ;
2016-09-08 14:11:32 +02:00
2016-05-10 16:42:13 -03:00
/* to put in an 1 bit instead, OR in tmp+1 */
2016-09-08 14:11:32 +02:00
addr = ( ( addr & ~ tmp ) < < 1 ) | ( addr & tmp ) ;
mask = mask & ( mask - 1 ) ;
2016-05-10 16:42:13 -03:00
}
2017-12-11 23:55:31 -08:00
2016-05-10 16:42:13 -03:00
return addr ;
}
2016-05-10 17:39:20 -03:00
static size_t mmap_reduce ( size_t addr , size_t mask )
2016-05-10 16:42:13 -03:00
{
while ( mask )
{
size_t tmp = ( mask - 1 ) & ~ mask ;
2016-09-08 14:11:32 +02:00
addr = ( addr & tmp ) | ( ( addr > > 1 ) & ~ tmp ) ;
mask = ( mask & ( mask - 1 ) ) > > 1 ;
2016-05-10 16:42:13 -03:00
}
2017-12-11 23:55:31 -08:00
2016-05-10 16:42:13 -03:00
return addr ;
}
2016-05-10 17:39:20 -03:00
static size_t mmap_highest_bit ( size_t n )
2016-05-10 16:42:13 -03:00
{
2016-05-10 17:39:20 -03:00
n = mmap_add_bits_down ( n ) ;
2016-05-10 16:42:13 -03:00
return n ^ ( n > > 1 ) ;
}
2016-11-13 20:58:09 +00:00
static bool mmap_preprocess_descriptors ( rarch_memory_descriptor_t * first , unsigned count )
2016-05-10 16:42:13 -03:00
{
2016-11-13 20:58:09 +00:00
size_t top_addr = 1 ;
rarch_memory_descriptor_t * desc = NULL ;
const rarch_memory_descriptor_t * end = first + count ;
2017-12-11 23:55:31 -08:00
2016-05-10 16:42:13 -03:00
for ( desc = first ; desc < end ; desc + + )
{
2016-11-13 20:58:09 +00:00
if ( desc - > core . select ! = 0 )
top_addr | = desc - > core . select ;
2016-05-10 16:42:13 -03:00
else
2016-11-13 20:58:09 +00:00
top_addr | = desc - > core . start + desc - > core . len - 1 ;
2016-05-10 16:42:13 -03:00
}
2017-12-11 23:55:31 -08:00
2016-05-10 17:39:20 -03:00
top_addr = mmap_add_bits_down ( top_addr ) ;
2017-12-11 23:55:31 -08:00
2016-05-10 16:42:13 -03:00
for ( desc = first ; desc < end ; desc + + )
{
2016-11-13 20:58:09 +00:00
if ( desc - > core . select = = 0 )
2016-05-10 16:42:13 -03:00
{
2016-11-13 20:58:09 +00:00
if ( desc - > core . len = = 0 )
2016-05-10 16:42:13 -03:00
return false ;
2017-12-11 23:55:31 -08:00
2016-11-13 20:58:09 +00:00
if ( ( desc - > core . len & ( desc - > core . len - 1 ) ) ! = 0 )
2016-05-10 16:42:13 -03:00
return false ;
2017-12-11 23:55:31 -08:00
2016-12-15 12:11:21 +01:00
desc - > core . select = top_addr & ~ mmap_inflate ( mmap_add_bits_down ( desc - > core . len - 1 ) ,
desc - > core . disconnect ) ;
2016-05-10 16:42:13 -03:00
}
2017-12-11 23:55:31 -08:00
2016-11-13 20:58:09 +00:00
if ( desc - > core . len = = 0 )
2016-12-15 12:11:21 +01:00
desc - > core . len = mmap_add_bits_down ( mmap_reduce ( top_addr & ~ desc - > core . select ,
desc - > core . disconnect ) ) + 1 ;
2017-12-11 23:55:31 -08:00
2016-11-13 20:58:09 +00:00
if ( desc - > core . start & ~ desc - > core . select )
2016-05-10 16:42:13 -03:00
return false ;
2017-12-11 23:55:31 -08:00
2016-11-13 20:58:09 +00:00
while ( mmap_reduce ( top_addr & ~ desc - > core . select , desc - > core . disconnect ) > > 1 > desc - > core . len - 1 )
desc - > core . disconnect | = mmap_highest_bit ( top_addr & ~ desc - > core . select & ~ desc - > core . disconnect ) ;
2017-12-11 23:55:31 -08:00
2016-11-13 20:58:09 +00:00
desc - > disconnect_mask = mmap_add_bits_down ( desc - > core . len - 1 ) ;
desc - > core . disconnect & = desc - > disconnect_mask ;
2017-12-11 23:55:31 -08:00
2016-11-13 20:58:09 +00:00
while ( ( ~ desc - > disconnect_mask ) > > 1 & desc - > core . disconnect )
2016-05-10 16:42:13 -03:00
{
2016-11-13 20:58:09 +00:00
desc - > disconnect_mask > > = 1 ;
desc - > core . disconnect & = desc - > disconnect_mask ;
2016-05-10 16:42:13 -03:00
}
}
2017-12-11 23:55:31 -08:00
2016-05-10 16:42:13 -03:00
return true ;
}
2016-08-31 03:34:34 +02:00
static bool dynamic_request_hw_context ( enum retro_hw_context_type type ,
unsigned minor , unsigned major )
{
switch ( type )
{
case RETRO_HW_CONTEXT_NONE :
RARCH_LOG ( " Requesting no HW context. \n " ) ;
break ;
case RETRO_HW_CONTEXT_VULKAN :
# ifdef HAVE_VULKAN
RARCH_LOG ( " Requesting Vulkan context. \n " ) ;
break ;
# else
RARCH_ERR ( " Requesting Vulkan context, but RetroArch is not compiled against Vulkan. Cannot use HW context. \n " ) ;
return false ;
# endif
# if defined(HAVE_OPENGLES)
# if (defined(HAVE_OPENGLES2) || defined(HAVE_OPENGLES3))
case RETRO_HW_CONTEXT_OPENGLES2 :
case RETRO_HW_CONTEXT_OPENGLES3 :
RARCH_LOG ( " Requesting OpenGLES%u context. \n " ,
type = = RETRO_HW_CONTEXT_OPENGLES2 ? 2 : 3 ) ;
break ;
# if defined(HAVE_OPENGLES3)
case RETRO_HW_CONTEXT_OPENGLES_VERSION :
RARCH_LOG ( " Requesting OpenGLES%u.%u context. \n " ,
major , minor ) ;
break ;
# endif
# endif
case RETRO_HW_CONTEXT_OPENGL :
case RETRO_HW_CONTEXT_OPENGL_CORE :
RARCH_ERR ( " Requesting OpenGL context, but RetroArch "
" is compiled against OpenGLES. Cannot use HW context. \n " ) ;
return false ;
2019-04-24 03:23:57 +02:00
# elif defined(HAVE_OPENGL) || defined(HAVE_OPENGL_CORE)
2016-08-31 03:34:34 +02:00
case RETRO_HW_CONTEXT_OPENGLES2 :
case RETRO_HW_CONTEXT_OPENGLES3 :
RARCH_ERR ( " Requesting OpenGLES%u context, but RetroArch "
" is compiled against OpenGL. Cannot use HW context. \n " ,
type = = RETRO_HW_CONTEXT_OPENGLES2 ? 2 : 3 ) ;
return false ;
case RETRO_HW_CONTEXT_OPENGLES_VERSION :
RARCH_ERR ( " Requesting OpenGLES%u.%u context, but RetroArch "
" is compiled against OpenGL. Cannot use HW context. \n " ,
major , minor ) ;
return false ;
case RETRO_HW_CONTEXT_OPENGL :
RARCH_LOG ( " Requesting OpenGL context. \n " ) ;
break ;
case RETRO_HW_CONTEXT_OPENGL_CORE :
2018-10-10 05:32:00 +02:00
/* TODO/FIXME - we should do a check here to see if
* the requested core GL version is supported */
2018-10-10 05:30:50 +02:00
RARCH_LOG ( " Requesting core OpenGL context (%u.%u). \n " ,
major , minor ) ;
2016-08-31 03:34:34 +02:00
break ;
# endif
2018-04-08 01:09:31 +02:00
# if defined(HAVE_D3D9) || defined(HAVE_D3D11)
case RETRO_HW_CONTEXT_DIRECT3D :
switch ( major )
{
2018-03-25 23:14:14 +01:00
# ifdef HAVE_D3D9
2018-04-08 01:09:31 +02:00
case 9 :
RARCH_LOG ( " Requesting D3D9 context. \n " ) ;
break ;
2018-03-25 23:14:14 +01:00
# endif
# ifdef HAVE_D3D11
2018-04-08 01:09:31 +02:00
case 11 :
RARCH_LOG ( " Requesting D3D11 context. \n " ) ;
break ;
# endif
default :
RARCH_LOG ( " Requesting unknown context. \n " ) ;
return false ;
}
break ;
2018-03-25 23:14:14 +01:00
# endif
2016-08-31 03:34:34 +02:00
default :
RARCH_LOG ( " Requesting unknown context. \n " ) ;
return false ;
}
return true ;
}
2016-08-31 03:42:58 +02:00
static bool dynamic_verify_hw_context ( enum retro_hw_context_type type ,
unsigned minor , unsigned major )
{
const char * video_ident = video_driver_get_ident ( ) ;
switch ( type )
{
case RETRO_HW_CONTEXT_VULKAN :
2017-05-29 02:16:25 +02:00
if ( ! string_is_equal ( video_ident , " vulkan " ) )
2016-08-31 03:42:58 +02:00
return false ;
break ;
case RETRO_HW_CONTEXT_OPENGLES2 :
case RETRO_HW_CONTEXT_OPENGLES3 :
case RETRO_HW_CONTEXT_OPENGLES_VERSION :
case RETRO_HW_CONTEXT_OPENGL :
case RETRO_HW_CONTEXT_OPENGL_CORE :
2019-03-02 11:53:14 +01:00
if ( ! string_is_equal ( video_ident , " gl " ) & &
! string_is_equal ( video_ident , " glcore " ) )
{
2016-08-31 03:42:58 +02:00
return false ;
2019-03-02 11:53:14 +01:00
}
2016-08-31 03:42:58 +02:00
break ;
2018-03-25 23:14:14 +01:00
case RETRO_HW_CONTEXT_DIRECT3D :
if ( ! ( string_is_equal ( video_ident , " d3d11 " ) & & major = = 11 ) )
return false ;
break ;
2016-08-31 03:42:58 +02:00
default :
break ;
}
return true ;
}
2017-01-25 16:53:06 +01:00
static void core_performance_counter_start ( struct retro_perf_counter * perf )
{
2017-05-15 05:06:23 +02:00
if ( rarch_ctl ( RARCH_CTL_IS_PERFCNT_ENABLE , NULL ) )
2017-01-25 16:53:06 +01:00
{
perf - > call_cnt + + ;
perf - > start = cpu_features_get_perf_counter ( ) ;
}
}
static void core_performance_counter_stop ( struct retro_perf_counter * perf )
{
2017-05-15 05:06:23 +02:00
if ( rarch_ctl ( RARCH_CTL_IS_PERFCNT_ENABLE , NULL ) )
2017-01-25 16:53:06 +01:00
perf - > total + = cpu_features_get_perf_counter ( ) - perf - > start ;
}
2018-09-11 13:29:20 -04:00
bool rarch_clear_all_thread_waits ( unsigned clear_threads , void * data )
{
if ( clear_threads > 0 )
audio_driver_start ( false ) ;
else
audio_driver_stop ( ) ;
return true ;
}
2015-01-15 02:48:40 +01:00
/**
* rarch_environment_cb :
* @ cmd : Identifier of command .
* @ data : Pointer to data .
*
* Environment callback function implementation .
*
* Returns : true ( 1 ) if environment callback command could
* be performed , otherwise false ( 0 ) .
* */
2013-08-24 22:35:54 +02:00
bool rarch_environment_cb ( unsigned cmd , void * data )
2011-10-27 23:40:34 +02:00
{
2014-12-05 14:29:40 +01:00
unsigned p ;
2015-12-07 14:26:21 +01:00
settings_t * settings = config_get_ptr ( ) ;
2017-04-23 16:41:26 +02:00
rarch_system_info_t * system = runloop_get_system_info ( ) ;
2017-12-11 23:55:31 -08:00
2014-09-21 09:33:51 -03:00
if ( ignore_environment_cb )
return false ;
2011-10-27 23:40:34 +02:00
switch ( cmd )
{
2012-04-07 11:55:37 +02:00
case RETRO_ENVIRONMENT_GET_OVERSCAN :
2017-04-28 00:53:06 +02:00
* ( bool * ) data = ! settings - > bools . video_crop_overscan ;
2014-09-02 05:57:53 +02:00
RARCH_LOG ( " Environ GET_OVERSCAN: %u \n " ,
2017-04-28 00:53:06 +02:00
( unsigned ) ! settings - > bools . video_crop_overscan ) ;
2011-11-09 22:18:48 +01:00
break ;
2012-04-07 11:55:37 +02:00
case RETRO_ENVIRONMENT_GET_CAN_DUPE :
2011-11-22 17:27:02 +01:00
* ( bool * ) data = true ;
2012-04-21 23:25:32 +02:00
RARCH_LOG ( " Environ GET_CAN_DUPE: true \n " ) ;
2011-12-02 19:12:47 +01:00
break ;
2012-04-07 11:55:37 +02:00
case RETRO_ENVIRONMENT_GET_VARIABLE :
2017-05-15 05:06:23 +02:00
if ( ! rarch_ctl ( RARCH_CTL_CORE_OPTIONS_GET , data ) )
2015-12-07 14:13:07 +01:00
{
struct retro_variable * var = ( struct retro_variable * ) data ;
2016-12-15 12:11:21 +01:00
if ( var )
{
2015-12-26 01:16:33 +01:00
RARCH_LOG ( " Environ GET_VARIABLE %s: not implemented. \n " , var - > key ) ;
2015-12-07 14:13:07 +01:00
var - > value = NULL ;
2015-12-24 23:04:15 -07:00
}
2015-12-07 14:13:07 +01:00
}
2012-02-06 15:51:35 +01:00
break ;
2013-04-04 13:58:30 +02:00
case RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE :
2017-05-15 05:06:23 +02:00
* ( bool * ) data = rarch_ctl ( RARCH_CTL_IS_CORE_OPTION_UPDATED , NULL ) ;
2013-04-04 13:58:30 +02:00
break ;
2012-04-07 11:55:37 +02:00
case RETRO_ENVIRONMENT_SET_VARIABLES :
2013-04-04 13:58:30 +02:00
RARCH_LOG ( " Environ SET_VARIABLES. \n " ) ;
2012-02-06 16:13:29 +01:00
2017-05-15 05:06:23 +02:00
rarch_ctl ( RARCH_CTL_CORE_OPTIONS_DEINIT , NULL ) ;
rarch_ctl ( RARCH_CTL_CORE_OPTIONS_INIT , data ) ;
2013-04-04 13:58:30 +02:00
2012-02-06 16:13:29 +01:00
break ;
2012-04-07 11:55:37 +02:00
case RETRO_ENVIRONMENT_SET_MESSAGE :
2012-03-12 00:37:44 +01:00
{
2012-04-07 11:55:37 +02:00
const struct retro_message * msg = ( const struct retro_message * ) data ;
2012-04-21 23:25:32 +02:00
RARCH_LOG ( " Environ SET_MESSAGE: %s \n " , msg - > msg ) ;
2019-05-11 17:24:00 +02:00
# ifdef HAVE_MENU_WIDGETS
2019-05-27 09:59:41 +02:00
if ( ! menu_widgets_set_libretro_message ( msg - > msg , roundf ( ( float ) msg - > frames / 60.0f * 1000.0f ) ) )
2019-05-11 17:24:00 +02:00
# endif
runloop_msg_queue_push ( msg - > msg , 3 , msg - > frames , true , NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_INFO ) ;
2012-03-12 00:37:44 +01:00
break ;
}
2012-04-07 11:55:37 +02:00
case RETRO_ENVIRONMENT_SET_ROTATION :
2012-03-30 19:09:34 +02:00
{
unsigned rotation = * ( const unsigned * ) data ;
2012-04-21 23:25:32 +02:00
RARCH_LOG ( " Environ SET_ROTATION: %u \n " , rotation ) ;
2017-04-28 00:53:06 +02:00
if ( ! settings - > bools . video_allow_rotate )
2012-04-01 16:12:04 +02:00
break ;
2016-06-30 17:40:19 +02:00
if ( system )
system - > rotation = rotation ;
2012-04-01 19:20:37 +02:00
2015-03-22 10:38:26 +01:00
if ( ! video_driver_set_rotation ( rotation ) )
2012-03-30 19:09:34 +02:00
return false ;
break ;
}
2012-05-22 20:14:07 +02:00
case RETRO_ENVIRONMENT_SHUTDOWN :
2012-06-12 00:28:34 +02:00
RARCH_LOG ( " Environ SHUTDOWN. \n " ) ;
2019-03-04 11:33:19 +00:00
/* 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 ) ;
2017-05-15 05:06:23 +02:00
rarch_ctl ( RARCH_CTL_SET_SHUTDOWN , NULL ) ;
rarch_ctl ( RARCH_CTL_SET_CORE_SHUTDOWN , NULL ) ;
2012-05-22 20:14:07 +02:00
break ;
2012-06-01 16:50:38 +02:00
case RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL :
2016-06-30 17:40:19 +02:00
if ( system )
{
system - > performance_level = * ( const unsigned * ) data ;
RARCH_LOG ( " Environ PERFORMANCE_LEVEL: %u. \n " ,
system - > performance_level ) ;
}
2012-06-12 00:28:34 +02:00
break ;
case RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY :
2017-08-05 13:48:37 -05:00
if ( string_is_empty ( settings - > paths . directory_system ) | | settings - > bools . systemfiles_in_content_dir )
2015-07-16 01:45:49 -05:00
{
2016-10-03 15:39:48 +02:00
const char * fullpath = path_get ( RARCH_PATH_CONTENT ) ;
if ( ! string_is_empty ( fullpath ) )
2016-05-26 18:09:46 +02:00
{
2017-09-09 21:41:38 +02:00
size_t path_size = PATH_MAX_LENGTH * sizeof ( char ) ;
char * temp_path = ( char * ) malloc ( PATH_MAX_LENGTH * sizeof ( char ) ) ;
2016-12-19 19:04:52 +01:00
temp_path [ 0 ] = ' \0 ' ;
2016-09-17 16:14:25 +02:00
2017-08-05 13:48:37 -05:00
if ( string_is_empty ( settings - > paths . directory_system ) )
RARCH_WARN ( " SYSTEM DIR is empty, assume CONTENT DIR %s \n " ,
fullpath ) ;
2017-09-09 21:41:38 +02:00
fill_pathname_basedir ( temp_path , fullpath , path_size ) ;
2016-10-03 08:20:33 +02:00
dir_set ( RARCH_DIR_SYSTEM , temp_path ) ;
2017-09-09 21:41:38 +02:00
free ( temp_path ) ;
2016-05-26 18:09:46 +02:00
}
2015-07-26 16:23:41 -05:00
2016-10-03 08:15:41 +02:00
* ( const char * * ) data = dir_get_ptr ( RARCH_DIR_SYSTEM ) ;
2015-08-19 19:20:27 -05:00
RARCH_LOG ( " Environ SYSTEM_DIRECTORY: \" %s \" . \n " ,
2016-10-03 08:15:41 +02:00
dir_get ( RARCH_DIR_SYSTEM ) ) ;
2015-07-16 01:45:49 -05:00
}
2015-08-19 19:20:27 -05:00
else
{
2017-04-29 00:39:29 +02:00
* ( const char * * ) data = settings - > paths . directory_system ;
2015-08-19 19:20:27 -05:00
RARCH_LOG ( " Environ SYSTEM_DIRECTORY: \" %s \" . \n " ,
2017-04-29 00:39:29 +02:00
settings - > paths . directory_system ) ;
2015-08-19 19:20:27 -05:00
}
2012-06-01 16:50:38 +02:00
break ;
2014-02-07 02:14:02 -05:00
case RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY :
2016-10-03 08:15:41 +02:00
* ( const char * * ) data = dir_get ( RARCH_DIR_CURRENT_SAVEFILE ) ;
2014-04-12 13:59:19 +02:00
break ;
2014-02-07 01:56:41 -05:00
2014-08-01 04:37:00 +02:00
case RETRO_ENVIRONMENT_GET_USERNAME :
2017-04-29 00:39:29 +02:00
* ( const char * * ) data = * settings - > paths . username ?
settings - > paths . username : NULL ;
2014-09-02 05:57:53 +02:00
RARCH_LOG ( " Environ GET_USERNAME: \" %s \" . \n " ,
2017-04-29 00:39:29 +02:00
settings - > paths . username ) ;
2014-08-01 04:37:00 +02:00
break ;
2014-08-01 07:45:56 +02:00
case RETRO_ENVIRONMENT_GET_LANGUAGE :
2016-06-07 06:05:41 +02:00
# ifdef HAVE_LANGEXTRA
2017-05-15 20:41:04 +02:00
{
unsigned user_lang = * msg_hash_get_uint ( MSG_HASH_USER_LANGUAGE ) ;
* ( unsigned * ) data = user_lang ;
RARCH_LOG ( " Environ GET_LANGUAGE: \" %u \" . \n " , user_lang ) ;
}
2016-06-07 06:05:41 +02:00
# endif
2014-08-01 07:45:56 +02:00
break ;
2012-06-16 15:07:31 +02:00
case RETRO_ENVIRONMENT_SET_PIXEL_FORMAT :
{
2015-10-19 19:52:53 -05:00
enum retro_pixel_format pix_fmt =
2014-09-02 05:57:53 +02:00
* ( const enum retro_pixel_format * ) data ;
2012-06-16 15:07:31 +02:00
switch ( pix_fmt )
{
case RETRO_PIXEL_FORMAT_0RGB1555 :
RARCH_LOG ( " Environ SET_PIXEL_FORMAT: 0RGB1555. \n " ) ;
break ;
2012-10-20 01:12:02 +02:00
case RETRO_PIXEL_FORMAT_RGB565 :
RARCH_LOG ( " Environ SET_PIXEL_FORMAT: RGB565. \n " ) ;
break ;
2012-06-16 15:07:31 +02:00
case RETRO_PIXEL_FORMAT_XRGB8888 :
RARCH_LOG ( " Environ SET_PIXEL_FORMAT: XRGB8888. \n " ) ;
break ;
default :
return false ;
}
2014-04-12 13:59:19 +02:00
2015-05-20 20:59:12 +02:00
video_driver_set_pixel_format ( pix_fmt ) ;
2012-06-16 15:07:31 +02:00
break ;
}
2012-09-09 23:35:23 +02:00
case RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS :
{
2016-06-30 17:40:19 +02:00
static const char * libretro_btn_desc [ ] = {
2015-06-26 17:46:13 +02:00
" B (bottom) " , " Y (left) " , " Select " , " Start " ,
" D-Pad Up " , " D-Pad Down " , " D-Pad Left " , " D-Pad Right " ,
" A (right) " , " X (up) " ,
" L " , " R " , " L2 " , " R2 " , " L3 " , " R3 " ,
} ;
2016-07-12 21:03:24 +02:00
if ( system )
{
unsigned retro_id ;
const struct retro_input_descriptor * desc = NULL ;
2019-04-12 17:28:53 +01:00
memset ( ( void * ) & system - > input_desc_btn , 0 ,
2016-07-12 21:03:24 +02:00
sizeof ( system - > input_desc_btn ) ) ;
2014-09-02 05:57:53 +02:00
2016-07-12 21:03:24 +02:00
desc = ( const struct retro_input_descriptor * ) data ;
2012-09-09 23:35:23 +02:00
2016-07-12 21:03:24 +02:00
for ( ; desc - > description ; desc + + )
{
unsigned retro_port = desc - > port ;
2016-01-26 05:06:11 +01:00
2016-07-12 21:03:24 +02:00
retro_id = desc - > id ;
2015-01-15 02:48:40 +01:00
2016-07-12 21:03:24 +02:00
if ( desc - > port > = MAX_USERS )
continue ;
2012-09-09 23:35:23 +02:00
2016-07-12 21:03:24 +02:00
/* Ignore all others for now. */
if ( desc - > device ! = RETRO_DEVICE_JOYPAD & &
desc - > device ! = RETRO_DEVICE_ANALOG )
continue ;
2012-09-09 23:35:23 +02:00
2016-07-12 21:03:24 +02:00
if ( desc - > id > = RARCH_FIRST_CUSTOM_BIND )
continue ;
2012-09-09 23:35:23 +02:00
2016-07-12 21:03:24 +02:00
if ( desc - > device = = RETRO_DEVICE_ANALOG )
2014-12-04 14:53:29 +01:00
{
2016-07-12 21:03:24 +02:00
switch ( retro_id )
{
case RETRO_DEVICE_ID_ANALOG_X :
switch ( desc - > index )
{
case RETRO_DEVICE_INDEX_ANALOG_LEFT :
system - > input_desc_btn [ retro_port ]
[ RARCH_ANALOG_LEFT_X_PLUS ] = desc - > description ;
system - > input_desc_btn [ retro_port ]
[ RARCH_ANALOG_LEFT_X_MINUS ] = desc - > description ;
break ;
case RETRO_DEVICE_INDEX_ANALOG_RIGHT :
system - > input_desc_btn [ retro_port ]
[ RARCH_ANALOG_RIGHT_X_PLUS ] = desc - > description ;
system - > input_desc_btn [ retro_port ]
[ RARCH_ANALOG_RIGHT_X_MINUS ] = desc - > description ;
break ;
}
break ;
case RETRO_DEVICE_ID_ANALOG_Y :
switch ( desc - > index )
{
case RETRO_DEVICE_INDEX_ANALOG_LEFT :
system - > input_desc_btn [ retro_port ]
[ RARCH_ANALOG_LEFT_Y_PLUS ] = desc - > description ;
system - > input_desc_btn [ retro_port ]
[ RARCH_ANALOG_LEFT_Y_MINUS ] = desc - > description ;
break ;
case RETRO_DEVICE_INDEX_ANALOG_RIGHT :
system - > input_desc_btn [ retro_port ]
[ RARCH_ANALOG_RIGHT_Y_PLUS ] = desc - > description ;
system - > input_desc_btn [ retro_port ]
[ RARCH_ANALOG_RIGHT_Y_MINUS ] = desc - > description ;
break ;
}
break ;
}
2014-12-04 14:53:29 +01:00
}
2016-07-12 21:03:24 +02:00
else
system - > input_desc_btn [ retro_port ]
[ retro_id ] = desc - > description ;
2014-12-04 14:53:29 +01:00
}
2012-09-09 23:35:23 +02:00
2016-07-12 21:03:24 +02:00
RARCH_LOG ( " Environ SET_INPUT_DESCRIPTORS: \n " ) ;
2017-05-11 07:36:21 +02:00
2012-09-09 23:35:23 +02:00
{
2019-04-28 02:03:56 +02:00
settings_t * settings = config_get_ptr ( ) ;
unsigned log_level = settings - > uints . libretro_log_level ;
if ( log_level = = RETRO_LOG_DEBUG )
2016-07-12 21:03:24 +02:00
{
2019-04-28 02:03:56 +02:00
unsigned max_users = * ( input_driver_get_uint ( INPUT_ACTION_MAX_USERS ) ) ;
for ( p = 0 ; p < max_users ; p + + )
2017-05-11 07:36:21 +02:00
{
2019-04-28 02:03:56 +02:00
for ( retro_id = 0 ; retro_id < RARCH_FIRST_CUSTOM_BIND ; retro_id + + )
{
const char * description = system - > input_desc_btn [ p ] [ retro_id ] ;
2015-01-09 21:30:07 +01:00
2019-04-28 02:03:56 +02:00
if ( ! description )
continue ;
2015-01-15 02:48:40 +01:00
2019-04-28 02:03:56 +02:00
RARCH_LOG ( " \t RetroPad, User %u, Button \" %s \" => \" %s \" \n " ,
p + 1 , libretro_btn_desc [ retro_id ] , description ) ;
}
2017-05-11 07:36:21 +02:00
}
2016-07-12 21:03:24 +02:00
}
2012-09-09 23:35:23 +02:00
}
2016-07-12 21:03:24 +02:00
core_set_input_descriptors ( ) ;
}
2014-12-04 13:45:56 +01:00
2012-09-09 23:35:23 +02:00
break ;
}
2014-04-12 13:59:19 +02:00
2012-11-25 20:23:31 -05:00
case RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK :
{
2016-01-21 01:52:02 +01:00
retro_keyboard_event_t * frontend_key_event = NULL ;
retro_keyboard_event_t * key_event = NULL ;
2015-10-19 19:52:53 -05:00
const struct retro_keyboard_callback * info =
2014-09-02 05:57:53 +02:00
( const struct retro_keyboard_callback * ) data ;
2015-01-09 21:30:07 +01:00
2017-05-15 05:06:23 +02:00
rarch_ctl ( RARCH_CTL_FRONTEND_KEY_EVENT_GET , & frontend_key_event ) ;
rarch_ctl ( RARCH_CTL_KEY_EVENT_GET , & key_event ) ;
2015-12-13 14:31:06 +01:00
2015-01-09 21:30:07 +01:00
RARCH_LOG ( " Environ SET_KEYBOARD_CALLBACK. \n " ) ;
2016-01-21 03:46:43 +01:00
if ( key_event )
* key_event = info - > callback ;
2016-05-26 18:09:46 +02:00
if ( frontend_key_event & & key_event )
2016-01-21 03:46:43 +01:00
* frontend_key_event = * key_event ;
2012-11-25 20:23:31 -05:00
break ;
}
2012-09-09 23:35:23 +02:00
2013-02-21 23:44:07 +01:00
case RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE :
RARCH_LOG ( " Environ SET_DISK_CONTROL_INTERFACE. \n " ) ;
2016-06-30 17:40:19 +02:00
if ( system )
system - > disk_control_cb =
* ( const struct retro_disk_control_callback * ) data ;
2013-02-21 23:44:07 +01:00
break ;
2013-03-27 16:15:15 +01:00
case RETRO_ENVIRONMENT_SET_HW_RENDER :
2014-09-02 05:57:53 +02:00
case RETRO_ENVIRONMENT_SET_HW_RENDER | RETRO_ENVIRONMENT_EXPERIMENTAL :
2013-03-27 16:15:15 +01:00
{
2015-10-19 19:52:53 -05:00
struct retro_hw_render_callback * cb =
2014-09-02 05:57:53 +02:00
( struct retro_hw_render_callback * ) data ;
2017-12-11 23:55:31 -08:00
struct retro_hw_render_callback * hwr =
2016-08-31 03:34:34 +02:00
video_driver_get_hw_context ( ) ;
2016-03-04 20:49:55 +01:00
2015-01-09 21:30:07 +01:00
RARCH_LOG ( " Environ SET_HW_RENDER. \n " ) ;
2016-08-31 03:34:34 +02:00
if ( ! dynamic_request_hw_context ( cb - > context_type , cb - > version_minor , cb - > version_major ) )
return false ;
2013-03-29 15:26:47 +01:00
2016-08-31 03:42:58 +02:00
if ( ! dynamic_verify_hw_context ( cb - > context_type , cb - > version_minor , cb - > version_major ) )
return false ;
2019-04-24 03:23:57 +02:00
# if defined(HAVE_OPENGL) || defined(HAVE_OPENGL_CORE)
2018-10-11 03:38:50 +02:00
if ( ! gl_set_core_context ( cb - > context_type ) ) { }
2018-10-10 18:24:41 +02:00
# endif
2018-10-10 05:30:50 +02:00
2015-01-19 04:19:30 +01:00
cb - > get_current_framebuffer = video_driver_get_current_framebuffer ;
cb - > get_proc_address = video_driver_get_proc_address ;
2013-06-22 15:06:56 +02:00
2016-01-26 05:03:41 +01:00
/* Old ABI. Don't copy garbage. */
2017-12-11 23:55:31 -08:00
if ( cmd & RETRO_ENVIRONMENT_EXPERIMENTAL )
2018-10-30 17:25:28 +01:00
{
2016-03-04 20:49:55 +01:00
memcpy ( hwr ,
2014-09-02 05:57:53 +02:00
cb , offsetof ( struct retro_hw_render_callback , stencil ) ) ;
2019-01-20 02:37:05 +01:00
memset ( ( uint8_t * ) hwr + offsetof ( struct retro_hw_render_callback , stencil ) ,
2018-12-29 04:39:13 +01:00
0 , sizeof ( * cb ) - offsetof ( struct retro_hw_render_callback , stencil ) ) ;
2018-10-30 17:25:28 +01:00
}
2013-06-22 15:06:56 +02:00
else
2016-03-04 20:49:55 +01:00
memcpy ( hwr , cb , sizeof ( * cb ) ) ;
2013-03-27 16:15:15 +01:00
break ;
}
2013-05-01 00:56:13 +02:00
case RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME :
{
bool state = * ( const bool * ) data ;
RARCH_LOG ( " Environ SET_SUPPORT_NO_GAME: %s. \n " , state ? " yes " : " no " ) ;
2016-03-02 06:20:36 +01:00
if ( state )
2016-05-08 05:17:31 +02:00
content_set_does_not_need_content ( ) ;
2016-03-02 06:20:36 +01:00
else
2016-05-08 05:17:31 +02:00
content_unset_does_not_need_content ( ) ;
2013-05-01 00:56:13 +02:00
break ;
2018-09-07 19:09:56 -04:00
}
case RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND :
{
bool state = * ( const bool * ) data ;
RARCH_LOG ( " Environ SET_SAVE_STATE_IN_BACKGROUND: %s. \n " , state ? " yes " : " no " ) ;
set_save_state_in_background ( state ) ;
break ;
2013-05-01 00:56:13 +02:00
}
2013-07-07 11:15:29 +02:00
case RETRO_ENVIRONMENT_GET_LIBRETRO_PATH :
{
const char * * path = ( const char * * ) data ;
# ifdef HAVE_DYNAMIC
2016-09-29 08:23:41 +02:00
* path = path_get ( RARCH_PATH_CORE ) ;
2016-07-25 06:47:15 +02:00
# else
* path = NULL ;
2013-07-07 11:15:29 +02:00
# endif
break ;
}
2013-07-14 13:09:53 +02:00
case RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK :
2016-09-11 13:03:19 +02:00
# ifdef HAVE_THREADS
2013-07-14 13:09:53 +02:00
{
2015-06-26 17:46:13 +02:00
RARCH_LOG ( " Environ SET_AUDIO_CALLBACK. \n " ) ;
2016-12-12 13:30:50 +01:00
# ifdef HAVE_NETWORKING
if ( netplay_driver_ctl ( RARCH_NETPLAY_CTL_IS_ENABLED , NULL ) )
return false ;
# endif
if ( recording_driver_get_data_ptr ( ) ) /* A/V sync is a must. */
return false ;
2016-05-08 16:45:58 +02:00
audio_driver_set_callback ( data ) ;
2013-07-14 13:09:53 +02:00
}
# endif
2016-05-13 04:53:35 +02:00
break ;
2013-07-14 13:09:53 +02:00
case RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK :
2013-07-14 13:43:01 +02:00
{
2013-07-14 13:09:53 +02:00
RARCH_LOG ( " Environ SET_FRAME_TIME_CALLBACK. \n " ) ;
2017-05-15 05:06:23 +02:00
rarch_ctl ( RARCH_CTL_SET_FRAME_TIME , data ) ;
2013-07-14 13:09:53 +02:00
break ;
2013-07-14 13:43:01 +02:00
}
2013-08-25 01:37:15 +02:00
2013-09-25 23:21:32 +02:00
case RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE :
{
2015-10-19 19:52:53 -05:00
struct retro_rumble_interface * iface =
2014-09-02 05:57:53 +02:00
( struct retro_rumble_interface * ) data ;
2015-01-09 21:30:07 +01:00
RARCH_LOG ( " Environ GET_RUMBLE_INTERFACE. \n " ) ;
2015-01-19 04:16:43 +01:00
iface - > set_rumble_state = input_driver_set_rumble_state ;
2013-09-25 23:21:32 +02:00
break ;
}
2013-11-02 21:39:43 +01:00
case RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES :
{
uint64_t * mask = ( uint64_t * ) data ;
2015-01-09 21:30:07 +01:00
RARCH_LOG ( " Environ GET_INPUT_DEVICE_CAPABILITIES. \n " ) ;
2016-05-08 23:12:04 +02:00
if ( input_driver_has_capabilities ( ) )
2015-03-23 04:18:27 +01:00
* mask = input_driver_get_capabilities ( ) ;
2013-11-02 21:39:43 +01:00
else
return false ;
break ;
}
2013-11-03 12:06:14 +01:00
case RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE :
{
2015-10-19 19:52:53 -05:00
struct retro_sensor_interface * iface =
2014-09-02 05:57:53 +02:00
( struct retro_sensor_interface * ) data ;
2015-01-09 21:30:07 +01:00
RARCH_LOG ( " Environ GET_SENSOR_INTERFACE. \n " ) ;
2015-01-18 19:28:51 +01:00
iface - > set_sensor_state = input_sensor_set_state ;
iface - > get_sensor_input = input_sensor_get_input ;
2013-11-03 12:06:14 +01:00
break ;
}
2013-11-12 16:00:18 +01:00
case RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE :
2013-11-12 12:00:57 +01:00
{
2014-09-02 05:57:53 +02:00
struct retro_camera_callback * cb =
( struct retro_camera_callback * ) data ;
2015-01-09 21:30:07 +01:00
RARCH_LOG ( " Environ GET_CAMERA_INTERFACE. \n " ) ;
2016-03-04 18:16:07 +01:00
cb - > start = driver_camera_start ;
cb - > stop = driver_camera_stop ;
2019-06-17 11:38:28 +02:00
rarch_ctl ( RARCH_CTL_CAMERA_SET_CB , cb ) ;
2016-03-04 18:16:07 +01:00
2015-12-05 14:39:52 +01:00
if ( cb - > caps ! = 0 )
2019-06-17 11:38:28 +02:00
rarch_ctl ( RARCH_CTL_CAMERA_SET_ACTIVE , NULL ) ;
2015-12-05 14:39:52 +01:00
else
2019-06-17 11:38:28 +02:00
rarch_ctl ( RARCH_CTL_CAMERA_UNSET_ACTIVE , NULL ) ;
2013-11-12 14:14:27 +01:00
break ;
2013-11-12 12:00:57 +01:00
}
2014-08-14 02:55:04 +02:00
2013-12-19 01:51:51 +01:00
case RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE :
{
2014-09-02 05:57:53 +02:00
struct retro_location_callback * cb =
( struct retro_location_callback * ) data ;
2015-01-09 21:30:07 +01:00
RARCH_LOG ( " Environ GET_LOCATION_INTERFACE. \n " ) ;
2015-06-25 12:57:54 +02:00
cb - > start = driver_location_start ;
cb - > stop = driver_location_stop ;
cb - > get_position = driver_location_get_position ;
cb - > set_interval = driver_location_set_interval ;
2016-06-30 17:40:19 +02:00
if ( system )
system - > location_cb = * cb ;
2015-12-05 15:40:29 +01:00
2019-06-17 11:57:46 +02:00
rarch_ctl ( RARCH_CTL_LOCATION_UNSET_ACTIVE , NULL ) ;
2013-12-19 01:51:51 +01:00
break ;
}
2013-11-12 12:00:57 +01:00
2013-12-09 10:32:12 +01:00
case RETRO_ENVIRONMENT_GET_LOG_INTERFACE :
{
struct retro_log_callback * cb = ( struct retro_log_callback * ) data ;
2015-01-09 21:30:07 +01:00
RARCH_LOG ( " Environ GET_LOG_INTERFACE. \n " ) ;
2013-12-09 10:32:12 +01:00
cb - > log = rarch_log_libretro ;
break ;
}
2013-12-17 19:10:21 +01:00
case RETRO_ENVIRONMENT_GET_PERF_INTERFACE :
{
struct retro_perf_callback * cb = ( struct retro_perf_callback * ) data ;
2015-01-09 21:30:07 +01:00
RARCH_LOG ( " Environ GET_PERF_INTERFACE. \n " ) ;
2016-05-10 09:17:04 +02:00
cb - > get_time_usec = cpu_features_get_time_usec ;
cb - > get_cpu_features = cpu_features_get ;
cb - > get_perf_counter = cpu_features_get_perf_counter ;
2016-01-26 05:03:41 +01:00
2017-12-11 23:55:31 -08:00
cb - > perf_register = performance_counter_register ;
2017-01-25 16:53:06 +01:00
cb - > perf_start = core_performance_counter_start ;
cb - > perf_stop = core_performance_counter_stop ;
2016-01-26 05:03:41 +01:00
cb - > perf_log = retro_perf_log ;
2013-12-17 19:10:21 +01:00
break ;
}
2015-03-16 02:59:30 +01:00
case RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY :
2014-02-20 22:48:31 +01:00
{
const char * * dir = ( const char * * ) data ;
2015-01-09 21:30:07 +01:00
2017-04-29 00:39:29 +02:00
* dir = * settings - > paths . directory_core_assets ?
settings - > paths . directory_core_assets : NULL ;
2015-03-16 02:59:30 +01:00
RARCH_LOG ( " Environ CORE_ASSETS_DIRECTORY: \" %s \" . \n " ,
2017-04-29 00:39:29 +02:00
settings - > paths . directory_core_assets ) ;
2014-02-20 22:48:31 +01:00
break ;
}
case RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO :
{
2014-02-20 23:05:56 +01:00
RARCH_LOG ( " Environ SET_SYSTEM_AV_INFO. \n " ) ;
2015-12-11 11:12:20 +01:00
return driver_ctl ( RARCH_DRIVER_CTL_UPDATE_SYSTEM_AV_INFO ,
( void * * ) & data ) ;
2014-02-20 22:48:31 +01:00
}
2014-04-04 17:04:01 +02:00
case RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO :
2014-04-04 14:58:42 +02:00
{
2019-04-28 01:55:49 +02:00
unsigned i ;
2015-10-19 19:52:53 -05:00
const struct retro_subsystem_info * info =
2014-09-02 05:57:53 +02:00
( const struct retro_subsystem_info * ) data ;
2019-04-28 01:55:49 +02:00
settings_t * settings = config_get_ptr ( ) ;
unsigned log_level = settings - > uints . libretro_log_level ;
2014-09-02 05:57:53 +02:00
2019-04-28 01:55:49 +02:00
if ( log_level = = RETRO_LOG_DEBUG )
RARCH_LOG ( " Environ SET_SUBSYSTEM_INFO. \n " ) ;
2015-01-09 21:30:07 +01:00
2014-04-04 14:58:42 +02:00
for ( i = 0 ; info [ i ] . ident ; i + + )
2014-04-04 16:02:53 +02:00
{
2019-04-28 01:55:49 +02:00
unsigned j ;
2019-04-30 11:38:47 +02:00
if ( log_level ! = RETRO_LOG_DEBUG )
2019-04-28 01:55:49 +02:00
continue ;
2014-04-04 16:02:53 +02:00
RARCH_LOG ( " Special game type: %s \n " , info [ i ] . desc ) ;
RARCH_LOG ( " Ident: %s \n " , info [ i ] . ident ) ;
RARCH_LOG ( " ID: %u \n " , info [ i ] . id ) ;
2014-07-28 20:01:27 +02:00
RARCH_LOG ( " Content: \n " ) ;
2014-04-04 16:02:53 +02:00
for ( j = 0 ; j < info [ i ] . num_roms ; j + + )
{
RARCH_LOG ( " %s (%s) \n " ,
2014-09-02 05:57:53 +02:00
info [ i ] . roms [ j ] . desc , info [ i ] . roms [ j ] . required ?
" required " : " optional " ) ;
2014-04-04 16:02:53 +02:00
}
}
2014-04-04 14:58:42 +02:00
2016-06-30 17:40:19 +02:00
if ( system )
{
2016-12-25 02:05:34 +01:00
struct retro_subsystem_info * info_ptr = NULL ;
2016-06-30 17:40:19 +02:00
free ( system - > subsystem . data ) ;
2016-12-25 02:05:34 +01:00
system - > subsystem . data = NULL ;
2018-10-30 17:25:28 +01:00
system - > subsystem . size = 0 ;
2014-09-02 05:57:53 +02:00
2016-12-25 02:05:34 +01:00
info_ptr = ( struct retro_subsystem_info * )
2018-10-30 17:25:28 +01:00
malloc ( i * sizeof ( * info_ptr ) ) ;
2016-12-25 02:05:34 +01:00
if ( ! info_ptr )
2016-06-30 17:40:19 +02:00
return false ;
2014-04-04 14:58:42 +02:00
2016-12-25 02:05:34 +01:00
system - > subsystem . data = info_ptr ;
2016-06-30 17:40:19 +02:00
memcpy ( system - > subsystem . data , info ,
i * sizeof ( * system - > subsystem . data ) ) ;
system - > subsystem . size = i ;
}
2014-04-04 14:58:42 +02:00
break ;
}
2014-04-12 13:22:24 +02:00
case RETRO_ENVIRONMENT_SET_CONTROLLER_INFO :
{
unsigned i , j ;
2015-10-19 19:52:53 -05:00
const struct retro_controller_info * info =
2014-09-02 05:57:53 +02:00
( const struct retro_controller_info * ) data ;
2019-04-28 02:03:56 +02:00
settings_t * settings = config_get_ptr ( ) ;
unsigned log_level = settings - > uints . libretro_log_level ;
2014-09-02 05:57:53 +02:00
2015-01-09 21:30:07 +01:00
RARCH_LOG ( " Environ SET_CONTROLLER_INFO. \n " ) ;
2014-04-12 13:22:24 +02:00
for ( i = 0 ; info [ i ] . types ; i + + )
{
2019-04-28 02:03:56 +02:00
if ( log_level ! = RETRO_LOG_DEBUG )
continue ;
2014-04-12 19:06:37 +02:00
RARCH_LOG ( " Controller port: %u \n " , i + 1 ) ;
2014-04-12 13:22:24 +02:00
for ( j = 0 ; j < info [ i ] . num_types ; j + + )
2014-09-02 05:57:53 +02:00
RARCH_LOG ( " %s (ID: %u) \n " , info [ i ] . types [ j ] . desc ,
info [ i ] . types [ j ] . id ) ;
2014-04-12 13:22:24 +02:00
}
2016-06-30 17:38:16 +02:00
if ( system )
{
2016-12-25 02:05:34 +01:00
struct retro_controller_info * info_ptr = NULL ;
2016-06-30 17:38:16 +02:00
free ( system - > ports . data ) ;
2016-12-25 02:05:34 +01:00
system - > ports . data = NULL ;
2018-10-30 17:25:28 +01:00
system - > ports . size = 0 ;
2016-12-25 02:05:34 +01:00
info_ptr = ( struct retro_controller_info * ) calloc ( i , sizeof ( * info_ptr ) ) ;
if ( ! info_ptr )
2016-06-30 17:38:16 +02:00
return false ;
2014-04-12 13:22:24 +02:00
2016-12-25 02:05:34 +01:00
system - > ports . data = info_ptr ;
2016-06-30 17:38:16 +02:00
memcpy ( system - > ports . data , info ,
i * sizeof ( * system - > ports . data ) ) ;
system - > ports . size = i ;
}
2014-04-12 13:22:24 +02:00
break ;
}
2017-12-11 23:55:31 -08:00
2016-05-10 08:04:41 -03:00
case RETRO_ENVIRONMENT_SET_MEMORY_MAPS :
{
2016-06-01 04:14:48 +02:00
if ( system )
{
2016-06-02 20:40:39 +02:00
unsigned i ;
const struct retro_memory_map * mmaps =
( const struct retro_memory_map * ) data ;
2016-11-13 20:58:09 +00:00
rarch_memory_descriptor_t * descriptors = NULL ;
2016-06-02 20:40:39 +02:00
2016-06-01 04:14:48 +02:00
RARCH_LOG ( " Environ SET_MEMORY_MAPS. \n " ) ;
free ( ( void * ) system - > mmaps . descriptors ) ;
2018-10-30 17:25:28 +01:00
system - > mmaps . descriptors = 0 ;
2016-06-01 04:14:48 +02:00
system - > mmaps . num_descriptors = 0 ;
2016-11-13 20:58:09 +00:00
descriptors = ( rarch_memory_descriptor_t * )
2016-06-01 04:14:48 +02:00
calloc ( mmaps - > num_descriptors ,
2016-11-13 20:58:09 +00:00
sizeof ( * descriptors ) ) ;
2016-06-01 04:14:48 +02:00
if ( ! descriptors )
return false ;
2016-12-25 02:05:34 +01:00
system - > mmaps . descriptors = descriptors ;
2016-06-01 04:14:48 +02:00
system - > mmaps . num_descriptors = mmaps - > num_descriptors ;
2016-11-13 20:58:09 +00:00
for ( i = 0 ; i < mmaps - > num_descriptors ; i + + )
system - > mmaps . descriptors [ i ] . core = mmaps - > descriptors [ i ] ;
2016-06-01 04:14:48 +02:00
mmap_preprocess_descriptors ( descriptors , mmaps - > num_descriptors ) ;
2016-06-02 20:40:39 +02:00
if ( sizeof ( void * ) = = 8 )
RARCH_LOG ( " ndx flags ptr offset start select disconn len addrspace \n " ) ;
else
RARCH_LOG ( " ndx flags ptr offset start select disconn len addrspace \n " ) ;
for ( i = 0 ; i < system - > mmaps . num_descriptors ; i + + )
{
2016-11-13 20:58:09 +00:00
const rarch_memory_descriptor_t * desc =
2016-06-02 20:40:39 +02:00
& system - > mmaps . descriptors [ i ] ;
char flags [ 7 ] ;
flags [ 0 ] = ' M ' ;
2016-11-13 20:58:09 +00:00
if ( ( desc - > core . flags & RETRO_MEMDESC_MINSIZE_8 ) = = RETRO_MEMDESC_MINSIZE_8 )
2016-06-02 20:40:39 +02:00
flags [ 1 ] = ' 8 ' ;
2016-11-13 20:58:09 +00:00
else if ( ( desc - > core . flags & RETRO_MEMDESC_MINSIZE_4 ) = = RETRO_MEMDESC_MINSIZE_4 )
2016-06-02 20:40:39 +02:00
flags [ 1 ] = ' 4 ' ;
2016-11-13 20:58:09 +00:00
else if ( ( desc - > core . flags & RETRO_MEMDESC_MINSIZE_2 ) = = RETRO_MEMDESC_MINSIZE_2 )
2016-06-02 20:40:39 +02:00
flags [ 1 ] = ' 2 ' ;
else
flags [ 1 ] = ' 1 ' ;
flags [ 2 ] = ' A ' ;
2016-11-13 20:58:09 +00:00
if ( ( desc - > core . flags & RETRO_MEMDESC_ALIGN_8 ) = = RETRO_MEMDESC_ALIGN_8 )
2016-06-02 20:40:39 +02:00
flags [ 3 ] = ' 8 ' ;
2016-11-13 20:58:09 +00:00
else if ( ( desc - > core . flags & RETRO_MEMDESC_ALIGN_4 ) = = RETRO_MEMDESC_ALIGN_4 )
2016-06-02 20:40:39 +02:00
flags [ 3 ] = ' 4 ' ;
2016-11-13 20:58:09 +00:00
else if ( ( desc - > core . flags & RETRO_MEMDESC_ALIGN_2 ) = = RETRO_MEMDESC_ALIGN_2 )
2016-06-02 20:40:39 +02:00
flags [ 3 ] = ' 2 ' ;
else
flags [ 3 ] = ' 1 ' ;
2016-11-13 20:58:09 +00:00
flags [ 4 ] = ( desc - > core . flags & RETRO_MEMDESC_BIGENDIAN ) ? ' B ' : ' b ' ;
flags [ 5 ] = ( desc - > core . flags & RETRO_MEMDESC_CONST ) ? ' C ' : ' c ' ;
2016-06-02 20:40:39 +02:00
flags [ 6 ] = 0 ;
RARCH_LOG ( " %03u %s %p %08X %08X %08X %08X %08X %s \n " ,
2016-11-13 20:58:09 +00:00
i + 1 , flags , desc - > core . ptr , desc - > core . offset , desc - > core . start ,
desc - > core . select , desc - > core . disconnect , desc - > core . len ,
desc - > core . addrspace ? desc - > core . addrspace : " " ) ;
2016-06-02 20:40:39 +02:00
}
2016-06-01 04:14:48 +02:00
}
else
{
RARCH_WARN ( " Environ SET_MEMORY_MAPS, but system pointer not initialized.. \n " ) ;
}
2016-06-25 21:00:58 +02:00
2016-05-10 08:04:41 -03:00
break ;
}
2014-04-12 13:22:24 +02:00
2014-06-07 13:19:28 +02:00
case RETRO_ENVIRONMENT_SET_GEOMETRY :
{
2016-01-26 05:03:41 +01:00
const struct retro_game_geometry * in_geom = NULL ;
struct retro_game_geometry * geom = NULL ;
2017-12-11 23:55:31 -08:00
struct retro_system_av_info * av_info =
2016-01-26 05:03:41 +01:00
video_viewport_get_system_av_info ( ) ;
2017-12-11 23:55:31 -08:00
2016-01-26 05:03:41 +01:00
if ( av_info )
geom = ( struct retro_game_geometry * ) & av_info - > geometry ;
2014-06-07 13:19:28 +02:00
2015-09-28 16:20:26 +02:00
if ( ! geom )
return false ;
2016-01-26 05:03:41 +01:00
in_geom = ( const struct retro_game_geometry * ) data ;
2015-01-09 21:30:07 +01:00
RARCH_LOG ( " Environ SET_GEOMETRY. \n " ) ;
2014-09-02 05:57:53 +02:00
/* Can potentially be called every frame,
* don ' t do anything unless required . */
2017-04-16 09:50:53 +02:00
if ( ( geom - > base_width ! = in_geom - > base_width ) | |
( geom - > base_height ! = in_geom - > base_height ) | |
( geom - > aspect_ratio ! = in_geom - > aspect_ratio ) )
2014-06-07 13:19:28 +02:00
{
geom - > base_width = in_geom - > base_width ;
geom - > base_height = in_geom - > base_height ;
geom - > aspect_ratio = in_geom - > aspect_ratio ;
2016-01-26 05:03:41 +01:00
2014-06-07 13:19:28 +02:00
RARCH_LOG ( " SET_GEOMETRY: %ux%u, aspect: %.3f. \n " ,
geom - > base_width , geom - > base_height , geom - > aspect_ratio ) ;
2015-10-19 19:52:53 -05:00
/* Forces recomputation of aspect ratios if
2014-09-02 05:57:53 +02:00
* using core - dependent aspect ratios . */
2016-05-09 20:51:53 +02:00
command_event ( CMD_EVENT_VIDEO_SET_ASPECT_RATIO , NULL ) ;
2015-10-19 19:52:53 -05:00
2014-09-02 05:57:53 +02:00
/* TODO: Figure out what to do, if anything, with recording. */
2014-06-07 13:19:28 +02:00
}
break ;
}
2015-12-25 19:29:14 +01:00
case RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER :
2016-05-08 14:00:51 +02:00
return video_driver_get_current_software_framebuffer (
2016-01-26 05:06:11 +01:00
( struct retro_framebuffer * ) data ) ;
2015-12-25 19:29:14 +01:00
2016-02-16 20:24:00 +01:00
case RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE :
2016-05-08 14:00:51 +02:00
return video_driver_get_hw_render_interface (
2016-02-16 20:24:00 +01:00
( const struct retro_hw_render_interface * * ) data ) ;
2017-12-11 23:55:31 -08:00
2016-05-12 22:03:18 -03:00
case RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS :
2016-05-13 04:41:46 +02:00
# ifdef HAVE_CHEEVOS
2016-05-13 04:53:35 +02:00
{
bool state = * ( const bool * ) data ;
RARCH_LOG ( " Environ SET_SUPPORT_ACHIEVEMENTS: %s. \n " , state ? " yes " : " no " ) ;
2019-05-29 14:26:22 -03:00
rcheevos_set_support_cheevos ( state ) ;
2016-05-13 04:53:35 +02:00
}
2016-05-13 04:41:46 +02:00
# endif
2016-06-25 21:00:58 +02:00
break ;
case RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE :
{
const struct retro_hw_render_context_negotiation_interface * iface =
( const struct retro_hw_render_context_negotiation_interface * ) data ;
RARCH_LOG ( " Environ SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE. \n " ) ;
video_driver_set_context_negotiation_interface ( iface ) ;
break ;
}
2016-02-16 20:24:00 +01:00
2016-09-30 14:16:48 -04:00
case RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS :
2016-09-30 18:36:02 -04:00
{
uint64_t * quirks = ( uint64_t * ) data ;
core_set_serialization_quirks ( * quirks ) ;
2016-09-30 14:16:48 -04:00
break ;
2016-09-30 18:36:02 -04:00
}
2016-09-30 14:16:48 -04:00
2017-08-07 18:05:43 +02:00
case RETRO_ENVIRONMENT_SET_HW_SHARED_CONTEXT :
{
core_set_shared_context = true ;
break ;
}
2019-02-03 15:49:35 -08:00
2017-12-14 15:06:28 +01:00
case RETRO_ENVIRONMENT_GET_VFS_INTERFACE :
{
2019-01-16 21:01:29 +01:00
const uint32_t supported_vfs_version = 3 ;
2017-12-14 15:06:28 +01:00
static struct retro_vfs_interface vfs_iface =
2019-01-20 02:37:05 +01:00
{
2019-01-16 21:01:29 +01:00
/* VFS API v1 */
2017-12-14 15:06:28 +01:00
retro_vfs_file_get_path_impl ,
retro_vfs_file_open_impl ,
retro_vfs_file_close_impl ,
retro_vfs_file_size_impl ,
retro_vfs_file_tell_impl ,
retro_vfs_file_seek_impl ,
retro_vfs_file_read_impl ,
retro_vfs_file_write_impl ,
retro_vfs_file_flush_impl ,
2019-01-16 21:01:29 +01:00
retro_vfs_file_remove_impl ,
2019-01-20 02:37:05 +01:00
retro_vfs_file_rename_impl ,
2019-01-16 21:01:29 +01:00
/* VFS API v2 */
2019-01-20 02:37:05 +01:00
retro_vfs_file_truncate_impl ,
2019-01-16 21:01:29 +01:00
/* VFS API v3 */
retro_vfs_stat_impl ,
retro_vfs_mkdir_impl ,
retro_vfs_opendir_impl ,
retro_vfs_readdir_impl ,
retro_vfs_dirent_get_name_impl ,
retro_vfs_dirent_is_dir_impl ,
retro_vfs_closedir_impl
2017-12-14 15:06:28 +01:00
} ;
struct retro_vfs_interface_info * vfs_iface_info = ( struct retro_vfs_interface_info * ) data ;
if ( vfs_iface_info - > required_interface_version < = supported_vfs_version )
{
2019-01-16 21:01:29 +01:00
RARCH_LOG ( " Core requested VFS version >= v%d, providing v%d \n " , vfs_iface_info - > required_interface_version , supported_vfs_version ) ;
2017-12-14 15:06:28 +01:00
vfs_iface_info - > required_interface_version = supported_vfs_version ;
vfs_iface_info - > iface = & vfs_iface ;
2019-01-14 21:30:20 +01:00
system - > supports_vfs = true ;
2017-12-14 15:06:28 +01:00
}
2019-01-16 21:01:29 +01:00
else
{
RARCH_WARN ( " Core requested VFS version v%d which is higher than what we support (v%d) \n " , vfs_iface_info - > required_interface_version , supported_vfs_version ) ;
return false ;
}
2017-12-14 15:06:28 +01:00
break ;
}
2017-12-27 11:05:12 -05:00
case RETRO_ENVIRONMENT_GET_LED_INTERFACE :
{
struct retro_led_interface * ledintf =
( struct retro_led_interface * ) data ;
2017-12-27 21:05:24 +01:00
if ( ledintf )
ledintf - > set_led_state = led_driver_set_led ;
2017-12-27 11:05:12 -05:00
}
2017-12-27 21:05:24 +01:00
break ;
2018-03-23 14:12:05 -05:00
case RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE :
{
int result = 0 ;
if ( ! audio_driver_is_suspended ( ) & & audio_driver_is_active ( ) )
result | = 2 ;
if ( video_driver_is_active ( ) & & ! video_driver_is_stub_frame ( ) )
result | = 1 ;
2018-03-30 20:22:35 -05:00
# ifdef HAVE_RUNAHEAD
if ( want_fast_savestate ( ) )
result | = 4 ;
if ( get_hard_disable_audio ( ) )
result | = 8 ;
2018-05-30 22:01:02 -04:00
# endif
# ifdef HAVE_NETWORKING
if ( netplay_driver_ctl ( RARCH_NETPLAY_CTL_IS_REPLAYING , NULL ) )
result & = ~ ( 1 | 2 ) ;
2018-10-07 09:53:13 -05:00
if ( netplay_driver_ctl ( RARCH_NETPLAY_CTL_IS_ENABLED , NULL ) )
result | = 4 ;
2018-03-30 20:22:35 -05:00
# endif
2018-03-23 14:12:05 -05:00
if ( data ! = NULL )
{
int * result_p = ( int * ) data ;
* result_p = result ;
}
2018-09-11 13:29:20 -04:00
break ;
2018-03-23 14:12:05 -05:00
}
2018-06-04 07:48:08 +02:00
case RETRO_ENVIRONMENT_GET_MIDI_INTERFACE :
{
struct retro_midi_interface * midi_interface =
( struct retro_midi_interface * ) data ;
if ( midi_interface )
{
midi_interface - > input_enabled = midi_driver_input_enabled ;
midi_interface - > output_enabled = midi_driver_output_enabled ;
midi_interface - > read = midi_driver_read ;
midi_interface - > write = midi_driver_write ;
midi_interface - > flush = midi_driver_flush ;
}
2018-09-11 13:29:20 -04:00
break ;
2018-06-04 07:48:08 +02:00
}
2018-09-08 02:19:05 +02:00
case RETRO_ENVIRONMENT_GET_FASTFORWARDING :
{
extern bool runloop_fastmotion ;
* ( bool * ) data = runloop_fastmotion ;
2018-09-11 13:29:20 -04:00
break ;
2018-09-08 02:19:05 +02:00
}
2018-09-11 13:29:20 -04:00
case RETRO_ENVIRONMENT_GET_CLEAR_ALL_THREAD_WAITS_CB :
{
* ( retro_environment_t * ) data = rarch_clear_all_thread_waits ;
break ;
}
2019-02-03 15:49:35 -08:00
2019-06-21 11:21:07 +02:00
case RETRO_ENVIRONMENT_GET_INPUT_BITMASKS :
/* Just falldown, the function will return true */
break ;
2019-02-27 04:43:14 +01:00
case RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE :
{
/* Try to use the polled refresh rate first. */
float target_refresh_rate = video_driver_get_refresh_rate ( ) ;
/* If the above function failed [possibly because it is not
* implemented ] , use the refresh rate set in the config instead . */
if ( target_refresh_rate = = 0.0 & & settings )
target_refresh_rate = settings - > floats . video_refresh_rate ;
* ( float * ) data = target_refresh_rate ;
break ;
}
2011-10-27 23:40:34 +02:00
default :
2012-04-21 23:25:32 +02:00
RARCH_LOG ( " Environ UNSUPPORTED (#%u). \n " , cmd ) ;
2011-10-27 23:40:34 +02:00
return false ;
}
return true ;
}