2012-04-21 21:13:50 +00:00
/* RetroArch - A frontend for libretro.
2014-01-01 00:50:59 +00:00
* Copyright ( C ) 2010 - 2014 - Hans - Kristian Arntzen
2017-03-22 02:09:18 +00:00
* Copyright ( C ) 2011 - 2017 - Daniel De Matteis
2015-01-07 16:46:50 +00:00
* Copyright ( C ) 2012 - 2015 - Michael Lelli
2017-08-05 05:37:26 +00:00
* Copyright ( C ) 2015 - 2017 - Andrés Suárez
2014-04-12 11:25:48 +00:00
*
2012-04-21 21:13:50 +00:00
* RetroArch is free software : you can redistribute it and / or modify it under the terms
2010-05-28 16:21:33 +00: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 21:13:50 +00:00
* RetroArch is distributed in the hope that it will be useful , but WITHOUT ANY WARRANTY ;
2010-05-28 16:21:33 +00: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 21:31:57 +00:00
* You should have received a copy of the GNU General Public License along with RetroArch .
2010-05-28 16:21:33 +00:00
* If not , see < http : //www.gnu.org/licenses/>.
*/
2016-09-06 21:52:33 +00:00
# ifdef _WIN32
# ifdef _XBOX
# include <xtl.h>
# else
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# endif
2018-12-11 01:03:03 +00:00
# if defined(DEBUG) && defined(HAVE_DRMINGW)
# include "exchndl.h"
# endif
2016-09-06 21:52:33 +00:00
# endif
2010-05-26 19:27:37 +00:00
# include <stdlib.h>
2017-05-11 07:11:46 +00:00
# include <stdarg.h>
2014-10-15 05:00:51 +00:00
# include <stdint.h>
2010-05-26 19:27:37 +00:00
# include <string.h>
2011-09-27 13:31:25 +00:00
# include <ctype.h>
2011-10-06 21:43:48 +00:00
# include <errno.h>
2015-12-05 20:31:46 +00:00
# include <setjmp.h>
2017-05-11 07:11:46 +00:00
# include <math.h>
2019-03-08 00:17:54 +00:00
# include <locale.h>
2015-12-05 20:31:46 +00:00
2014-10-22 02:27:51 +00:00
# include <boolean.h>
2015-12-26 06:07:01 +00:00
# include <string/stdstring.h>
2016-03-20 13:53:54 +00:00
# include <lists/string_list.h>
2017-06-28 02:41:38 +00:00
# include <retro_timers.h>
2015-06-14 14:45:20 +00:00
# include <compat/strl.h>
# include <compat/getopt.h>
2017-05-14 23:28:34 +00:00
# include <audio/audio_mixer.h>
2015-06-14 14:45:20 +00:00
# include <compat/posix_string.h>
2017-12-14 19:05:46 +00:00
# include <streams/file_stream.h>
2015-06-14 14:45:20 +00:00
# include <file/file_path.h>
2016-02-05 12:51:30 +00:00
# include <retro_assert.h>
2016-10-01 04:02:18 +00:00
# include <retro_miscellaneous.h>
2017-05-11 07:11:46 +00:00
# include <queues/message_queue.h>
# include <queues/task_queue.h>
2016-05-10 18:31:27 +00:00
# include <features/features_cpu.h>
2019-03-08 00:17:54 +00:00
# include <lists/dir_list.h>
# include <net/net_http.h>
2019-03-01 00:22:35 +00:00
# include "runtime_file.h"
2016-05-10 18:31:27 +00:00
2016-09-08 04:07:43 +00:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
2019-02-27 15:47:39 +00:00
# include <audio/audio_resampler.h>
2016-09-08 04:07:43 +00:00
# ifdef HAVE_MENU
# include "menu/menu_driver.h"
2018-11-22 14:45:52 +00:00
# include "menu/menu_animation.h"
2018-09-25 14:46:15 +00:00
# include "menu/menu_input.h"
2017-05-11 07:11:46 +00:00
# include "menu/widgets/menu_dialog.h"
2017-05-25 13:40:29 +00:00
# include "menu/widgets/menu_input_dialog.h"
2019-02-21 09:23:21 +00:00
# ifdef HAVE_MENU_WIDGETS
# include "menu/widgets/menu_widgets.h"
# endif
2017-05-11 07:11:46 +00:00
# endif
# ifdef HAVE_CHEEVOS
# include "cheevos/cheevos.h"
2016-09-08 04:07:43 +00:00
# endif
2018-05-29 04:43:30 +00:00
# ifdef HAVE_DISCORD
# include "discord/discord.h"
# endif
2016-10-03 02:13:34 +00:00
# ifdef HAVE_NETWORKING
# include "network/netplay/netplay.h"
# endif
2017-05-11 07:11:46 +00:00
# if defined(HAVE_HTTPSERVER) && defined(HAVE_ZLIB)
# include "network/httpserver/httpserver.h"
# endif
# ifdef HAVE_THREADS
# include <rthreads/rthreads.h>
# endif
# include "autosave.h"
2019-01-05 21:47:05 +00:00
# include "command.h"
2016-09-08 04:07:43 +00:00
# include "config.features.h"
2016-01-19 22:15:19 +00:00
# include "content.h"
2016-03-22 01:56:06 +00:00
# include "core_type.h"
2015-12-07 07:56:11 +00:00
# include "core_info.h"
2016-03-22 02:49:05 +00:00
# include "dynamic.h"
2016-09-11 14:31:23 +00:00
# include "driver.h"
2017-05-11 07:11:46 +00:00
# include "input/input_driver.h"
2015-07-01 17:30:34 +00:00
# include "msg_hash.h"
2015-12-01 00:47:26 +00:00
# include "movie.h"
2016-09-17 12:49:35 +00:00
# include "dirs.h"
2016-09-17 10:10:46 +00:00
# include "paths.h"
2016-06-11 19:55:55 +00:00
# include "file_path_special.h"
2017-05-11 07:11:46 +00:00
# include "ui/ui_companion_driver.h"
2015-11-23 11:03:38 +00:00
# include "verbosity.h"
2015-06-14 14:45:20 +00:00
2015-12-05 08:09:31 +00:00
# include "frontend/frontend_driver.h"
2015-11-29 20:34:45 +00:00
# include "audio/audio_driver.h"
2019-03-08 00:17:54 +00:00
# ifdef HAVE_THREADS
# include "../gfx/video_thread_wrapper.h"
# endif
2019-02-27 15:47:39 +00:00
# include "gfx/video_driver.h"
2017-05-11 07:11:46 +00:00
# include "camera/camera_driver.h"
2015-12-05 15:12:29 +00:00
# include "record/record_driver.h"
2019-02-27 15:47:39 +00:00
# include "location/location_driver.h"
# include "wifi/wifi_driver.h"
# include "led/led_driver.h"
# include "midi/midi_driver.h"
2016-05-08 03:29:10 +00:00
# include "core.h"
2015-04-07 01:22:33 +00:00
# include "configuration.h"
2017-05-11 07:11:46 +00:00
# include "list_special.h"
# include "managers/core_option_manager.h"
2016-05-09 16:20:52 +00:00
# include "managers/cheat_manager.h"
2017-05-11 07:11:46 +00:00
# include "managers/state_manager.h"
2019-01-20 02:16:58 +00:00
# include "tasks/task_content.h"
2016-05-16 15:19:16 +00:00
# include "tasks/tasks_internal.h"
2018-01-27 01:27:29 +00:00
# include "performance_counters.h"
2015-01-24 22:42:31 +00:00
2016-09-01 15:49:28 +00:00
# include "version.h"
# include "version_git.h"
2010-12-24 00:07:27 +00:00
2015-10-27 23:55:11 +00:00
# include "retroarch.h"
2018-03-29 13:38:22 +00:00
# ifdef HAVE_RUNAHEAD
2018-03-28 19:22:07 +00:00
# include "runahead/run_ahead.h"
2018-03-29 13:38:22 +00:00
# endif
2018-03-28 19:22:07 +00:00
2016-09-17 12:23:44 +00:00
# define _PSUPP(var, name, desc) printf(" %s:\n\t\t%s: %s\n", name, desc, _##var##_supp ? "yes" : "no")
# define FAIL_CPU(simd_type) do { \
RARCH_ERR ( simd_type " code is compiled in, but CPU does not support this feature. Cannot continue. \n " ) ; \
retroarch_fail ( 1 , " validate_cpu_features() " ) ; \
} while ( 0 )
2017-05-11 07:11:46 +00:00
# ifdef HAVE_ZLIB
# define DEFAULT_EXT "zip"
# else
# define DEFAULT_EXT ""
# endif
2018-01-27 01:27:29 +00:00
# define SHADER_FILE_WATCH_DELAY_MSEC 500
2018-12-19 19:53:17 +00:00
# define HOLD_START_DELAY_SEC 2
2018-01-26 00:09:55 +00:00
2019-02-25 18:12:50 +00:00
# define QUIT_DELAY_USEC 3 * 1000000 /* 3 seconds */
2019-03-08 00:17:54 +00:00
# define DEBUG_INFO_FILENAME "debug_info.txt"
2016-01-26 04:38:40 +00:00
/* Descriptive names for options without short variant.
*
* Please keep the name in sync with the option name .
* Order does not matter . */
2015-11-30 03:10:15 +00:00
enum
{
2015-06-30 20:39:13 +00:00
RA_OPT_MENU = 256 , /* must be outside the range of a char */
2016-12-16 04:09:55 +00:00
RA_OPT_STATELESS ,
2016-09-15 03:54:18 +00:00
RA_OPT_CHECK_FRAMES ,
2015-06-12 15:42:44 +00:00
RA_OPT_PORT ,
RA_OPT_SPECTATE ,
RA_OPT_NICK ,
RA_OPT_COMMAND ,
RA_OPT_APPENDCONFIG ,
RA_OPT_BPS ,
RA_OPT_IPS ,
RA_OPT_NO_PATCH ,
RA_OPT_RECORDCONFIG ,
2015-06-18 00:30:53 +00:00
RA_OPT_SUBSYSTEM ,
2015-06-12 15:42:44 +00:00
RA_OPT_SIZE ,
RA_OPT_FEATURES ,
RA_OPT_VERSION ,
RA_OPT_EOF_EXIT ,
2018-08-19 03:09:40 +00:00
RA_OPT_MAX_FRAMES ,
RA_OPT_MAX_FRAMES_SCREENSHOT ,
RA_OPT_MAX_FRAMES_SCREENSHOT_PATH
2015-06-12 15:42:44 +00:00
} ;
2017-05-11 07:11:46 +00:00
enum runloop_state
{
2017-05-20 12:14:27 +00:00
RUNLOOP_STATE_ITERATE = 0 ,
2017-05-29 18:30:01 +00:00
RUNLOOP_STATE_POLLED_AND_SLEEP ,
2017-05-11 07:11:46 +00:00
RUNLOOP_STATE_SLEEP ,
RUNLOOP_STATE_MENU_ITERATE ,
RUNLOOP_STATE_END ,
RUNLOOP_STATE_QUIT
} ;
typedef struct runloop_ctx_msg_info
{
const char * msg ;
unsigned prio ;
unsigned duration ;
bool flush ;
} runloop_ctx_msg_info_t ;
2016-09-17 12:23:44 +00:00
static jmp_buf error_sjlj_context ;
2018-08-19 03:09:40 +00:00
static enum rarch_core_type current_core_type = CORE_TYPE_PLAIN ;
static enum rarch_core_type explicit_current_core_type = CORE_TYPE_PLAIN ;
static char error_string [ 255 ] = { 0 } ;
2018-01-30 03:11:08 +00:00
static char runtime_shader_preset [ 255 ] = { 0 } ;
2015-11-30 18:30:05 +00:00
2017-05-12 01:39:37 +00:00
# ifdef HAVE_THREAD_STORAGE
static sthread_tls_t rarch_tls ;
2018-08-19 03:09:40 +00:00
const void * MAGIC_POINTER = ( void * ) ( uintptr_t ) 0x0DEFACED ;
2017-05-12 01:39:37 +00:00
# endif
2016-10-01 07:52:07 +00:00
static retro_bits_t has_set_libretro_device ;
2017-05-12 01:39:37 +00:00
2018-08-19 03:09:40 +00:00
static bool has_set_core = false ;
2018-05-29 09:06:43 +00:00
# ifdef HAVE_DISCORD
2018-09-09 21:41:50 +00:00
bool discord_is_inited = false ;
2018-08-19 03:09:40 +00:00
# endif
static bool rarch_is_inited = false ;
static bool rarch_error_on_init = false ;
static bool rarch_force_fullscreen = false ;
2018-12-12 00:34:12 +00:00
static bool rarch_is_switching_display_mode = false ;
2018-08-19 03:09:40 +00:00
static bool has_set_verbosity = false ;
static bool has_set_libretro = false ;
static bool has_set_libretro_directory = false ;
static bool has_set_save_path = false ;
static bool has_set_state_path = false ;
static bool has_set_netplay_mode = false ;
static bool has_set_netplay_ip_address = false ;
static bool has_set_netplay_ip_port = false ;
static bool has_set_netplay_stateless_mode = false ;
static bool has_set_netplay_check_frames = false ;
static bool has_set_ups_pref = false ;
static bool has_set_bps_pref = false ;
static bool has_set_ips_pref = false ;
static bool rarch_is_sram_load_disabled = false ;
static bool rarch_is_sram_save_disabled = false ;
static bool rarch_use_sram = false ;
static bool rarch_ups_pref = false ;
static bool rarch_bps_pref = false ;
static bool rarch_ips_pref = false ;
2019-02-27 15:47:39 +00:00
static bool runloop_force_nonblock = false ;
2018-08-19 03:09:40 +00:00
static bool runloop_paused = false ;
static bool runloop_idle = false ;
static bool runloop_slowmotion = false ;
2018-09-08 00:19:05 +00:00
bool runloop_fastmotion = false ;
2018-08-19 03:09:40 +00:00
static bool runloop_shutdown_initiated = false ;
static bool runloop_core_shutdown_initiated = false ;
static bool runloop_perfcnt_enable = false ;
static bool runloop_overrides_active = false ;
static bool runloop_remaps_core_active = false ;
static bool runloop_remaps_game_active = false ;
static bool runloop_remaps_content_dir_active = false ;
static bool runloop_game_options_active = false ;
static bool runloop_autosave = false ;
2017-09-08 04:08:05 +00:00
static rarch_system_info_t runloop_system ;
static struct retro_frame_time_callback runloop_frame_time ;
2018-08-19 03:09:40 +00:00
static retro_keyboard_event_t runloop_key_event = NULL ;
static retro_keyboard_event_t runloop_frontend_key_event = NULL ;
static core_option_manager_t * runloop_core_options = NULL ;
2017-09-08 04:08:05 +00:00
# ifdef HAVE_THREADS
2018-08-19 03:09:40 +00:00
static slock_t * _runloop_msg_queue_lock = NULL ;
2017-09-08 04:08:05 +00:00
# endif
2018-08-19 03:09:40 +00:00
static msg_queue_t * runloop_msg_queue = NULL ;
2017-09-08 04:08:05 +00:00
2018-08-19 03:09:40 +00:00
static unsigned runloop_pending_windowed_scale = 0 ;
static unsigned runloop_max_frames = 0 ;
static bool runloop_max_frames_screenshot = false ;
static char runloop_max_frames_screenshot_path [ PATH_MAX_LENGTH ] = { 0 } ;
static unsigned fastforward_after_frames = 0 ;
2017-09-08 04:08:05 +00:00
2018-08-19 03:09:40 +00:00
static retro_usec_t runloop_frame_time_last = 0 ;
static retro_time_t frame_limit_minimum_time = 0.0 ;
static retro_time_t frame_limit_last_time = 0.0 ;
2019-03-04 15:30:12 +00:00
static retro_time_t libretro_core_runtime_last = 0 ;
2019-02-12 05:32:01 +00:00
static retro_time_t libretro_core_runtime_usec = 0 ;
2017-05-11 07:11:46 +00:00
2019-03-06 12:24:35 +00:00
static char runtime_content_path [ PATH_MAX_LENGTH ] = { 0 } ;
static char runtime_core_path [ PATH_MAX_LENGTH ] = { 0 } ;
2019-03-21 16:56:24 +00:00
static bool log_file_created = false ;
2019-03-25 17:22:59 +00:00
static char timestamped_log_file_name [ 64 ] = { 0 } ;
2019-03-21 16:56:24 +00:00
2017-05-21 19:42:13 +00:00
extern bool input_driver_flushing_input ;
2019-01-05 20:11:58 +00:00
static char launch_arguments [ 4096 ] ;
2019-02-27 15:47:39 +00:00
/**
* find_driver_nonempty :
* @ label : string of driver type to be found .
* @ i : index of driver .
* @ str : identifier name of the found driver
* gets written to this string .
* @ len : size of @ str .
*
* Find driver based on @ label .
*
* Returns : NULL if no driver based on @ label found , otherwise
* pointer to driver .
* */
static const void * find_driver_nonempty ( const char * label , int i ,
char * s , size_t len )
{
const void * drv = NULL ;
if ( string_is_equal ( label , " camera_driver " ) )
{
drv = camera_driver_find_handle ( i ) ;
if ( drv )
strlcpy ( s , camera_driver_find_ident ( i ) , len ) ;
}
else if ( string_is_equal ( label , " location_driver " ) )
{
drv = location_driver_find_handle ( i ) ;
if ( drv )
strlcpy ( s , location_driver_find_ident ( i ) , len ) ;
}
# ifdef HAVE_MENU
else if ( string_is_equal ( label , " menu_driver " ) )
{
drv = menu_driver_find_handle ( i ) ;
if ( drv )
strlcpy ( s , menu_driver_find_ident ( i ) , len ) ;
}
# endif
else if ( string_is_equal ( label , " input_driver " ) )
{
drv = input_driver_find_handle ( i ) ;
if ( drv )
strlcpy ( s , input_driver_find_ident ( i ) , len ) ;
}
else if ( string_is_equal ( label , " input_joypad_driver " ) )
{
drv = joypad_driver_find_handle ( i ) ;
if ( drv )
strlcpy ( s , joypad_driver_find_ident ( i ) , len ) ;
}
else if ( string_is_equal ( label , " video_driver " ) )
{
drv = video_driver_find_handle ( i ) ;
if ( drv )
strlcpy ( s , video_driver_find_ident ( i ) , len ) ;
}
else if ( string_is_equal ( label , " audio_driver " ) )
{
drv = audio_driver_find_handle ( i ) ;
if ( drv )
strlcpy ( s , audio_driver_find_ident ( i ) , len ) ;
}
else if ( string_is_equal ( label , " record_driver " ) )
{
drv = record_driver_find_handle ( i ) ;
if ( drv )
strlcpy ( s , record_driver_find_ident ( i ) , len ) ;
}
else if ( string_is_equal ( label , " midi_driver " ) )
{
drv = midi_driver_find_handle ( i ) ;
if ( drv )
strlcpy ( s , midi_driver_find_ident ( i ) , len ) ;
}
else if ( string_is_equal ( label , " audio_resampler_driver " ) )
{
drv = audio_resampler_driver_find_handle ( i ) ;
if ( drv )
strlcpy ( s , audio_resampler_driver_find_ident ( i ) , len ) ;
}
else if ( string_is_equal ( label , " wifi_driver " ) )
{
drv = wifi_driver_find_handle ( i ) ;
if ( drv )
strlcpy ( s , wifi_driver_find_ident ( i ) , len ) ;
}
return drv ;
}
/**
* driver_find_index :
* @ label : string of driver type to be found .
* @ drv : identifier of driver to be found .
*
* Find index of the driver , based on @ label .
*
* Returns : - 1 if no driver based on @ label and @ drv found , otherwise
* index number of the driver found in the array .
* */
static int driver_find_index ( const char * label , const char * drv )
{
unsigned i ;
char str [ 256 ] ;
str [ 0 ] = ' \0 ' ;
for ( i = 0 ;
find_driver_nonempty ( label , i , str , sizeof ( str ) ) ! = NULL ; i + + )
{
if ( string_is_empty ( str ) )
break ;
if ( string_is_equal_noncase ( drv , str ) )
return i ;
}
return - 1 ;
}
static bool driver_find_first ( const char * label , char * s , size_t len )
{
find_driver_nonempty ( label , 0 , s , len ) ;
return true ;
}
/**
* driver_find_last :
* @ label : string of driver type to be found .
* @ s : identifier of driver to be found .
* @ len : size of @ s .
*
* Find last driver in driver array .
* */
static bool driver_find_last ( const char * label , char * s , size_t len )
{
unsigned i ;
for ( i = 0 ;
find_driver_nonempty ( label , i , s , len ) ! = NULL ; i + + )
{ }
if ( i )
find_driver_nonempty ( label , i - 1 , s , len ) ;
else
driver_find_first ( label , s , len ) ;
return true ;
}
/**
* driver_find_prev :
* @ label : string of driver type to be found .
* @ s : identifier of driver to be found .
* @ len : size of @ s .
*
* Find previous driver in driver array .
* */
static bool driver_find_prev ( const char * label , char * s , size_t len )
{
int i = driver_find_index ( label , s ) ;
if ( i > 0 )
{
find_driver_nonempty ( label , i - 1 , s , len ) ;
return true ;
}
RARCH_WARN (
" Couldn't find any previous driver (current one: \" %s \" ). \n " , s ) ;
return false ;
}
/**
* driver_find_next :
* @ label : string of driver type to be found .
* @ s : identifier of driver to be found .
* @ len : size of @ s .
*
* Find next driver in driver array .
* */
bool driver_find_next ( const char * label , char * s , size_t len )
{
int i = driver_find_index ( label , s ) ;
if ( i > = 0 & & string_is_not_equal ( s , " null " ) )
{
find_driver_nonempty ( label , i + 1 , s , len ) ;
return true ;
}
RARCH_WARN ( " %s (current one: \" %s \" ). \n " ,
msg_hash_to_str ( MSG_COULD_NOT_FIND_ANY_NEXT_DRIVER ) ,
s ) ;
return false ;
}
static void driver_adjust_system_rates ( void )
{
audio_driver_monitor_adjust_system_rates ( ) ;
video_driver_monitor_adjust_system_rates ( ) ;
if ( ! video_driver_get_ptr ( false ) )
return ;
if ( runloop_force_nonblock )
command_event ( CMD_EVENT_VIDEO_SET_NONBLOCKING_STATE , NULL ) ;
else
driver_set_nonblock_state ( ) ;
}
/**
* driver_set_nonblock_state :
*
* Sets audio and video drivers to nonblock state ( if enabled ) .
*
* If nonblock state is false , sets
* blocking state for both audio and video drivers instead .
* */
void driver_set_nonblock_state ( void )
{
bool enable = input_driver_is_nonblock_state ( ) ;
/* Only apply non-block-state for video if we're using vsync. */
if ( video_driver_is_active ( ) & & video_driver_get_ptr ( false ) )
{
settings_t * settings = config_get_ptr ( ) ;
bool video_nonblock = enable ;
if ( ! settings - > bools . video_vsync | | runloop_force_nonblock )
video_nonblock = true ;
video_driver_set_nonblock_state ( video_nonblock ) ;
}
audio_driver_set_nonblocking_state ( enable ) ;
}
/**
* driver_update_system_av_info :
* @ data : pointer to new A / V info
*
* Update the system Audio / Video information .
* Will reinitialize audio / video drivers .
* Used by RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO .
*
* Returns : true ( 1 ) if successful , otherwise false ( 0 ) .
* */
static bool driver_update_system_av_info ( const struct retro_system_av_info * info )
{
struct retro_system_av_info * av_info = video_viewport_get_system_av_info ( ) ;
settings_t * settings = config_get_ptr ( ) ;
memcpy ( av_info , info , sizeof ( * av_info ) ) ;
command_event ( CMD_EVENT_REINIT , NULL ) ;
/* Cannot continue recording with different parameters.
* Take the easiest route out and just restart the recording . */
if ( recording_driver_get_data_ptr ( ) )
{
runloop_msg_queue_push (
msg_hash_to_str ( MSG_RESTARTING_RECORDING_DUE_TO_DRIVER_REINIT ) ,
2 , 180 , false ,
NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_INFO ) ;
command_event ( CMD_EVENT_RECORD_DEINIT , NULL ) ;
command_event ( CMD_EVENT_RECORD_INIT , NULL ) ;
}
/* Hide mouse cursor in fullscreen after
* a RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO call . */
if ( settings - > bools . video_fullscreen )
video_driver_hide_mouse ( ) ;
return true ;
}
/**
* drivers_init :
* @ flags : Bitmask of drivers to initialize .
*
* Initializes drivers .
* @ flags determines which drivers get initialized .
* */
void drivers_init ( int flags )
{
bool video_is_threaded = false ;
# ifdef HAVE_MENU
/* By default, we want the menu to persist through driver reinits. */
menu_driver_ctl ( RARCH_MENU_CTL_SET_OWN_DRIVER , NULL ) ;
# endif
if ( flags & ( DRIVER_VIDEO_MASK | DRIVER_AUDIO_MASK ) )
driver_adjust_system_rates ( ) ;
2019-02-27 16:02:33 +00:00
/* Initialize video driver */
2019-02-27 15:47:39 +00:00
if ( flags & DRIVER_VIDEO_MASK )
{
struct retro_hw_render_callback * hwr =
video_driver_get_hw_context ( ) ;
video_driver_monitor_reset ( ) ;
video_driver_init ( & video_is_threaded ) ;
if ( ! video_driver_is_video_cache_context_ack ( )
& & hwr - > context_reset )
hwr - > context_reset ( ) ;
video_driver_unset_video_cache_context_ack ( ) ;
runloop_frame_time_last = 0 ;
}
2019-02-27 16:02:33 +00:00
/* Initialize audio driver */
2019-02-27 15:47:39 +00:00
if ( flags & DRIVER_AUDIO_MASK )
{
audio_driver_init ( ) ;
audio_driver_new_devices_list ( ) ;
}
2019-02-27 16:02:33 +00:00
if ( flags & DRIVER_CAMERA_MASK )
{
/* Only initialize camera driver if we're ever going to use it. */
if ( camera_driver_ctl ( RARCH_CAMERA_CTL_IS_ACTIVE , NULL ) )
camera_driver_ctl ( RARCH_CAMERA_CTL_INIT , NULL ) ;
}
2019-02-27 15:47:39 +00:00
2019-02-27 16:02:33 +00:00
if ( flags & DRIVER_LOCATION_MASK )
{
/* Only initialize location driver if we're ever going to use it. */
if ( location_driver_ctl ( RARCH_LOCATION_CTL_IS_ACTIVE , NULL ) )
init_location ( ) ;
}
2019-02-27 15:47:39 +00:00
core_info_init_current_core ( ) ;
# ifdef HAVE_MENU
# ifdef HAVE_MENU_WIDGETS
if ( video_driver_has_widgets ( ) )
{
menu_widgets_init ( video_is_threaded ) ;
menu_widgets_context_reset ( video_is_threaded ) ;
}
# endif
if ( flags & DRIVER_VIDEO_MASK )
{
2019-02-27 16:02:33 +00:00
/* Initialize menu driver */
2019-02-27 15:47:39 +00:00
if ( flags & DRIVER_MENU_MASK )
menu_driver_init ( video_is_threaded ) ;
}
# else
/* Qt uses core info, even if the menu is disabled */
command_event ( CMD_EVENT_CORE_INFO_INIT , NULL ) ;
command_event ( CMD_EVENT_LOAD_CORE_PERSIST , NULL ) ;
# endif
if ( flags & ( DRIVER_VIDEO_MASK | DRIVER_AUDIO_MASK ) )
{
/* Keep non-throttled state as good as possible. */
if ( input_driver_is_nonblock_state ( ) )
driver_set_nonblock_state ( ) ;
}
2019-02-27 16:02:33 +00:00
/* Initialize LED driver */
2019-02-27 15:47:39 +00:00
if ( flags & DRIVER_LED_MASK )
led_driver_init ( ) ;
2019-02-27 16:02:33 +00:00
/* Initialize MIDI driver */
2019-02-27 15:47:39 +00:00
if ( flags & DRIVER_MIDI_MASK )
midi_driver_init ( ) ;
}
/**
* uninit_drivers :
* @ flags : Bitmask of drivers to deinitialize .
*
* Deinitializes drivers .
*
*
* @ flags determines which drivers get deinitialized .
* */
/**
* Driver ownership - set this to true if the platform in question needs to ' own '
* the respective handle and therefore skip regular RetroArch
* driver teardown / reiniting procedure .
*
* If to true , the ' free ' function will get skipped . It is
* then up to the driver implementation to properly handle
* ' reiniting ' inside the ' init ' function and make sure it
* returns the existing handle instead of allocating and
* returning a pointer to a new handle .
*
* Typically , if a driver intends to make use of this , it should
* set this to true at the end of its ' init ' function .
* */
void driver_uninit ( int flags )
{
core_info_deinit_list ( ) ;
core_info_free_current_core ( ) ;
# ifdef HAVE_MENU
if ( flags & DRIVER_MENU_MASK )
{
menu_driver_ctl ( RARCH_MENU_CTL_DEINIT , NULL ) ;
menu_driver_free ( ) ;
}
# endif
2019-02-27 16:02:33 +00:00
if ( ( flags & DRIVER_LOCATION_MASK ) )
2019-02-27 15:47:39 +00:00
location_driver_ctl ( RARCH_LOCATION_CTL_DEINIT , NULL ) ;
2019-02-27 16:02:33 +00:00
if ( ( flags & DRIVER_CAMERA_MASK ) )
2019-02-27 15:47:39 +00:00
camera_driver_ctl ( RARCH_CAMERA_CTL_DEINIT , NULL ) ;
2019-02-27 16:02:33 +00:00
if ( ( flags & DRIVER_WIFI_MASK ) )
2019-02-27 15:47:39 +00:00
wifi_driver_ctl ( RARCH_WIFI_CTL_DEINIT , NULL ) ;
if ( flags & DRIVER_LED )
led_driver_free ( ) ;
if ( flags & DRIVERS_VIDEO_INPUT )
video_driver_free ( ) ;
if ( flags & DRIVER_AUDIO_MASK )
audio_driver_deinit ( ) ;
2019-02-27 16:09:15 +00:00
if ( ( flags & DRIVER_VIDEO_MASK ) )
2019-02-27 15:47:39 +00:00
video_driver_destroy_data ( ) ;
2019-02-27 16:17:34 +00:00
if ( ( flags & DRIVER_INPUT_MASK ) )
2019-02-27 15:47:39 +00:00
input_driver_destroy_data ( ) ;
2019-02-27 16:09:15 +00:00
if ( ( flags & DRIVER_AUDIO_MASK ) )
2019-02-27 15:47:39 +00:00
audio_driver_destroy_data ( ) ;
if ( flags & DRIVER_MIDI_MASK )
midi_driver_free ( ) ;
}
bool driver_ctl ( enum driver_ctl_state state , void * data )
{
switch ( state )
{
case RARCH_DRIVER_CTL_DEINIT :
# if defined(HAVE_MENU) && defined(HAVE_MENU_WIDGETS)
/* Tear down menu widgets no matter what
* in case the handle is lost in the threaded
* video driver in the meantime
* ( breaking video_driver_has_widgets ) */
menu_widgets_context_destroy ( ) ;
menu_widgets_free ( ) ;
# endif
video_driver_destroy ( ) ;
audio_driver_destroy ( ) ;
input_driver_destroy ( ) ;
# ifdef HAVE_MENU
menu_driver_destroy ( ) ;
# endif
location_driver_ctl ( RARCH_LOCATION_CTL_DESTROY , NULL ) ;
camera_driver_ctl ( RARCH_CAMERA_CTL_DESTROY , NULL ) ;
wifi_driver_ctl ( RARCH_WIFI_CTL_DESTROY , NULL ) ;
core_uninit_libretro_callbacks ( ) ;
break ;
case RARCH_DRIVER_CTL_SET_REFRESH_RATE :
{
float * hz = ( float * ) data ;
video_monitor_set_refresh_rate ( * hz ) ;
audio_driver_monitor_set_rate ( ) ;
driver_adjust_system_rates ( ) ;
}
break ;
case RARCH_DRIVER_CTL_UPDATE_SYSTEM_AV_INFO :
{
const struct retro_system_av_info * * info = ( const struct retro_system_av_info * * ) data ;
if ( info )
return driver_update_system_av_info ( * info ) ;
}
return false ;
case RARCH_DRIVER_CTL_FIND_FIRST :
{
driver_ctx_info_t * drv = ( driver_ctx_info_t * ) data ;
if ( ! drv )
return false ;
return driver_find_first ( drv - > label , drv - > s , drv - > len ) ;
}
case RARCH_DRIVER_CTL_FIND_LAST :
{
driver_ctx_info_t * drv = ( driver_ctx_info_t * ) data ;
if ( ! drv )
return false ;
return driver_find_last ( drv - > label , drv - > s , drv - > len ) ;
}
case RARCH_DRIVER_CTL_FIND_PREV :
{
driver_ctx_info_t * drv = ( driver_ctx_info_t * ) data ;
if ( ! drv )
return false ;
return driver_find_prev ( drv - > label , drv - > s , drv - > len ) ;
}
case RARCH_DRIVER_CTL_FIND_NEXT :
{
driver_ctx_info_t * drv = ( driver_ctx_info_t * ) data ;
if ( ! drv )
return false ;
return driver_find_next ( drv - > label , drv - > s , drv - > len ) ;
}
case RARCH_DRIVER_CTL_FIND_INDEX :
{
driver_ctx_info_t * drv = ( driver_ctx_info_t * ) data ;
if ( ! drv )
return false ;
drv - > len = driver_find_index ( drv - > label , drv - > s ) ;
}
break ;
case RARCH_DRIVER_CTL_NONE :
default :
break ;
}
return true ;
}
2019-02-12 05:32:01 +00:00
void rarch_core_runtime_tick ( void )
{
2019-03-04 15:30:12 +00:00
retro_time_t frame_time ;
2019-02-12 05:32:01 +00:00
struct retro_system_av_info * av_info = video_viewport_get_system_av_info ( ) ;
if ( av_info & & av_info - > timing . fps )
2019-03-04 15:30:12 +00:00
{
frame_time = ( 1.0 / av_info - > timing . fps ) * 1000000 ;
/* Account for slow motion */
if ( runloop_slowmotion )
{
settings_t * settings = config_get_ptr ( ) ;
if ( settings )
frame_time = ( retro_time_t ) ( ( double ) frame_time * settings - > floats . slowmotion_ratio ) ;
}
/* Account for fast forward */
else if ( runloop_fastmotion )
{
/* Doing it this way means we miss the first frame after
* turning fast forward on , but it saves the overhead of
* having to do :
* retro_time_t current_usec = cpu_features_get_time_usec ( ) ;
* libretro_core_runtime_last = current_usec ;
* every frame when fast forward is off . */
retro_time_t current_usec = cpu_features_get_time_usec ( ) ;
if ( current_usec - libretro_core_runtime_last < frame_time )
{
frame_time = current_usec - libretro_core_runtime_last ;
}
libretro_core_runtime_last = current_usec ;
}
libretro_core_runtime_usec + = frame_time ;
}
2019-02-12 05:32:01 +00:00
}
2019-03-07 12:28:21 +00:00
static void update_runtime_log ( bool log_per_core )
{
runtime_log_t * runtime_log = NULL ;
/* Initialise runtime log file */
runtime_log = runtime_log_init ( runtime_content_path , runtime_core_path , log_per_core ) ;
if ( runtime_log )
{
/* Add additional runtime */
runtime_log_add_runtime_usec ( runtime_log , libretro_core_runtime_usec ) ;
/* Update 'last played' entry */
runtime_log_set_last_played_now ( runtime_log ) ;
/* Save runtime log file */
runtime_log_save ( runtime_log ) ;
/* Clean up */
free ( runtime_log ) ;
}
2019-02-12 05:32:01 +00:00
}
2017-10-30 03:27:56 +00:00
# ifdef HAVE_THREADS
void runloop_msg_queue_lock ( void )
2017-05-11 07:20:35 +00:00
{
2017-10-30 03:27:56 +00:00
slock_lock ( _runloop_msg_queue_lock ) ;
}
2017-05-11 07:20:35 +00:00
2017-10-30 03:27:56 +00:00
void runloop_msg_queue_unlock ( void )
{
slock_unlock ( _runloop_msg_queue_lock ) ;
}
# endif
static void retroarch_msg_queue_deinit ( void )
{
2017-05-11 07:20:35 +00:00
# ifdef HAVE_THREADS
2017-10-30 03:27:56 +00:00
runloop_msg_queue_lock ( ) ;
2017-05-11 07:20:35 +00:00
# endif
2017-10-30 03:27:56 +00:00
if ( ! runloop_msg_queue )
return ;
2017-05-11 07:20:35 +00:00
msg_queue_free ( runloop_msg_queue ) ;
# ifdef HAVE_THREADS
2017-10-30 03:27:56 +00:00
runloop_msg_queue_unlock ( ) ;
2017-05-11 07:20:35 +00:00
slock_free ( _runloop_msg_queue_lock ) ;
_runloop_msg_queue_lock = NULL ;
# endif
runloop_msg_queue = NULL ;
}
static void retroarch_msg_queue_init ( void )
{
retroarch_msg_queue_deinit ( ) ;
runloop_msg_queue = msg_queue_new ( 8 ) ;
# ifdef HAVE_THREADS
_runloop_msg_queue_lock = slock_new ( ) ;
# endif
}
2017-05-20 09:34:51 +00:00
static void retroarch_override_setting_free_state ( void )
{
2017-09-08 22:20:39 +00:00
unsigned i ;
2017-05-20 09:34:51 +00:00
for ( i = 0 ; i < RARCH_OVERRIDE_SETTING_LAST ; i + + )
{
if ( i = = RARCH_OVERRIDE_SETTING_LIBRETRO_DEVICE )
{
2017-09-08 22:20:39 +00:00
unsigned j ;
2017-05-20 09:34:51 +00:00
for ( j = 0 ; j < MAX_USERS ; j + + )
retroarch_override_setting_unset ( ( enum rarch_override_setting ) ( i ) , & j ) ;
}
else
retroarch_override_setting_unset ( ( enum rarch_override_setting ) ( i ) , NULL ) ;
}
}
2017-05-11 07:20:35 +00:00
static void global_free ( void )
{
global_t * global = NULL ;
2017-05-27 01:43:53 +00:00
content_deinit ( ) ;
2017-05-11 07:20:35 +00:00
path_deinit_subsystem ( ) ;
command_event ( CMD_EVENT_RECORD_DEINIT , NULL ) ;
command_event ( CMD_EVENT_LOG_FILE_DEINIT , NULL ) ;
2019-01-12 16:58:35 +00:00
rarch_ctl ( RARCH_CTL_UNSET_BLOCK_CONFIG_READ , NULL ) ;
2017-05-12 01:39:37 +00:00
rarch_is_sram_load_disabled = false ;
rarch_is_sram_save_disabled = false ;
rarch_use_sram = false ;
2019-01-12 16:58:35 +00:00
rarch_ctl ( RARCH_CTL_UNSET_BPS_PREF , NULL ) ;
rarch_ctl ( RARCH_CTL_UNSET_IPS_PREF , NULL ) ;
rarch_ctl ( RARCH_CTL_UNSET_UPS_PREF , NULL ) ;
rarch_ctl ( RARCH_CTL_UNSET_PATCH_BLOCKED , NULL ) ;
2017-05-12 01:39:37 +00:00
runloop_overrides_active = false ;
2017-08-05 05:37:26 +00:00
runloop_remaps_core_active = false ;
runloop_remaps_game_active = false ;
2018-05-14 04:17:44 +00:00
runloop_remaps_content_dir_active = false ;
2017-05-11 07:20:35 +00:00
core_unset_input_descriptors ( ) ;
global = global_get_ptr ( ) ;
path_clear_all ( ) ;
dir_clear_all ( ) ;
2017-09-29 18:47:54 +00:00
if ( global )
{
2017-10-04 04:53:47 +00:00
if ( ! string_is_empty ( global - > name . remapfile ) )
2017-09-29 18:47:54 +00:00
free ( global - > name . remapfile ) ;
2019-01-10 21:24:43 +00:00
memset ( global , 0 , sizeof ( struct global ) ) ;
2017-09-29 18:47:54 +00:00
}
2017-05-11 07:20:35 +00:00
retroarch_override_setting_free_state ( ) ;
}
2016-05-09 05:24:28 +00:00
static void retroarch_print_features ( void )
2011-01-25 12:03:53 +00:00
{
2018-08-18 17:43:49 +00:00
frontend_driver_attach_console ( ) ;
2011-01-25 12:03:53 +00:00
puts ( " " ) ;
puts ( " Features: " ) ;
2016-06-20 02:51:36 +00:00
_PSUPP ( libretrodb , " LibretroDB " , " LibretroDB support " ) ;
_PSUPP ( command , " Command " , " Command interface support " ) ;
2016-01-26 04:38:40 +00:00
_PSUPP ( network_command , " Network Command " , " Network Command interface "
" support " ) ;
2016-06-20 02:51:36 +00:00
_PSUPP ( sdl , " SDL " , " SDL input/audio/video drivers " ) ;
_PSUPP ( sdl2 , " SDL2 " , " SDL2 input/audio/video drivers " ) ;
_PSUPP ( x11 , " X11 " , " X11 input/video drivers " ) ;
_PSUPP ( wayland , " wayland " , " Wayland input/video drivers " ) ;
_PSUPP ( thread , " Threads " , " Threading support " ) ;
_PSUPP ( vulkan , " Vulkan " , " Vulkan video driver " ) ;
2018-06-21 04:29:53 +00:00
_PSUPP ( metal , " Metal " , " Metal video driver " ) ;
2016-06-20 02:51:36 +00:00
_PSUPP ( opengl , " OpenGL " , " OpenGL video driver support " ) ;
_PSUPP ( opengles , " OpenGL ES " , " OpenGLES video driver support " ) ;
_PSUPP ( xvideo , " XVideo " , " Video driver " ) ;
_PSUPP ( udev , " UDEV " , " UDEV/EVDEV input driver support " ) ;
_PSUPP ( egl , " EGL " , " Video context driver " ) ;
_PSUPP ( kms , " KMS " , " Video context driver " ) ;
_PSUPP ( vg , " OpenVG " , " Video context driver " ) ;
_PSUPP ( coreaudio , " CoreAudio " , " Audio driver " ) ;
2019-01-31 22:14:20 +00:00
_PSUPP ( coreaudio3 , " CoreAudioV3 " , " Audio driver " ) ;
2016-06-20 02:51:36 +00:00
_PSUPP ( alsa , " ALSA " , " Audio driver " ) ;
_PSUPP ( oss , " OSS " , " Audio driver " ) ;
_PSUPP ( jack , " Jack " , " Audio driver " ) ;
_PSUPP ( rsound , " RSound " , " Audio driver " ) ;
_PSUPP ( roar , " RoarAudio " , " Audio driver " ) ;
_PSUPP ( pulse , " PulseAudio " , " Audio driver " ) ;
_PSUPP ( dsound , " DirectSound " , " Audio driver " ) ;
2017-04-09 21:53:55 +00:00
_PSUPP ( wasapi , " WASAPI " , " Audio driver " ) ;
2016-06-20 02:51:36 +00:00
_PSUPP ( xaudio , " XAudio2 " , " Audio driver " ) ;
_PSUPP ( al , " OpenAL " , " Audio driver " ) ;
_PSUPP ( sl , " OpenSL " , " Audio driver " ) ;
_PSUPP ( 7 zip , " 7zip " , " 7zip extraction support " ) ;
_PSUPP ( zlib , " zlib " , " .zip extraction support " ) ;
_PSUPP ( dylib , " External " , " External filter and plugin support " ) ;
_PSUPP ( cg , " Cg " , " Fragment/vertex shader driver " ) ;
_PSUPP ( glsl , " GLSL " , " Fragment/vertex shader driver " ) ;
_PSUPP ( glsl , " HLSL " , " Fragment/vertex shader driver " ) ;
_PSUPP ( sdl_image , " SDL_image " , " SDL_image image loading " ) ;
_PSUPP ( rpng , " rpng " , " PNG image loading/encoding " ) ;
_PSUPP ( rpng , " rjpeg " , " JPEG image loading " ) ;
_PSUPP ( dynamic , " Dynamic " , " Dynamic run-time loading of "
" libretro library " ) ;
_PSUPP ( ffmpeg , " FFmpeg " , " On-the-fly recording of gameplay "
" with libavcodec " ) ;
_PSUPP ( freetype , " FreeType " , " TTF font rendering driver " ) ;
_PSUPP ( coretext , " CoreText " , " TTF font rendering driver "
" (for OSX and/or iOS) " ) ;
_PSUPP ( netplay , " Netplay " , " Peer-to-peer netplay " ) ;
_PSUPP ( python , " Python " , " Script support in shaders " ) ;
_PSUPP ( libusb , " Libusb " , " Libusb support " ) ;
_PSUPP ( cocoa , " Cocoa " , " Cocoa UI companion support "
" (for OSX and/or iOS) " ) ;
2016-11-29 13:23:26 +00:00
_PSUPP ( qt , " Qt " , " Qt UI companion support " ) ;
2016-06-20 02:51:36 +00:00
_PSUPP ( v4l2 , " Video4Linux2 " , " Camera driver " ) ;
2011-01-25 12:03:53 +00:00
}
# undef _PSUPP
2016-05-09 05:09:26 +00:00
static void retroarch_print_version ( void )
2010-10-01 19:39:15 +00:00
{
2016-10-27 07:44:20 +00:00
char str [ 255 ] ;
2018-08-18 17:43:49 +00:00
frontend_driver_attach_console ( ) ;
2016-10-21 03:57:40 +00:00
str [ 0 ] = ' \0 ' ;
2015-04-16 18:17:05 +00:00
2016-06-20 01:54:42 +00:00
fprintf ( stderr , " %s: %s -- v%s " ,
msg_hash_to_str ( MSG_PROGRAM ) ,
msg_hash_to_str ( MSG_LIBRETRO_FRONTEND ) ,
PACKAGE_VERSION ) ;
2014-01-11 17:51:42 +00:00
# ifdef HAVE_GIT_VERSION
2016-05-11 18:44:24 +00:00
printf ( " -- %s -- \n " , retroarch_git_version ) ;
2014-01-11 17:51:42 +00:00
# endif
2016-05-09 05:09:26 +00:00
retroarch_get_capabilities ( RARCH_CAPABILITIES_COMPILER , str , sizeof ( str ) ) ;
2015-04-16 18:19:53 +00:00
fprintf ( stdout , " %s " , str ) ;
2015-04-16 18:17:05 +00:00
fprintf ( stdout , " Built: %s \n " , __DATE__ ) ;
2015-06-12 14:42:29 +00:00
}
/**
2016-05-09 05:09:26 +00:00
* retroarch_print_help :
2015-06-12 14:42:29 +00:00
*
2015-06-30 13:26:14 +00:00
* Prints help message explaining the program ' s commandline switches .
2015-06-12 14:42:29 +00:00
* */
2016-05-09 05:09:26 +00:00
static void retroarch_print_help ( const char * arg0 )
2015-06-12 14:42:29 +00:00
{
2018-08-18 17:43:49 +00:00
frontend_driver_attach_console ( ) ;
2015-06-12 15:43:38 +00:00
puts ( " =================================================================== " ) ;
2016-05-09 05:09:26 +00:00
retroarch_print_version ( ) ;
2015-06-12 15:43:38 +00:00
puts ( " =================================================================== " ) ;
2015-06-12 13:15:27 +00:00
printf ( " Usage: %s [OPTIONS]... [FILE] \n " , arg0 ) ;
2015-06-12 14:18:36 +00:00
puts ( " -h, --help Show this help message. " ) ;
2015-06-12 14:42:29 +00:00
puts ( " -v, --verbose Verbose logging. " ) ;
2015-07-02 22:16:46 +00:00
puts ( " --version Show version. " ) ;
2016-01-26 04:38:40 +00:00
puts ( " --features Prints available features compiled into "
" program. " ) ;
2015-10-28 07:02:39 +00:00
# ifdef HAVE_MENU
2016-01-26 04:38:40 +00:00
puts ( " --menu Do not require content or libretro core to "
" be loaded, \n "
" starts directly in menu. If no arguments "
" are passed to \n "
" the program, it is equivalent to using "
" --menu as only argument. " ) ;
2015-10-28 07:02:39 +00:00
# endif
2015-06-12 16:09:00 +00:00
puts ( " -s, --save=PATH Path for save files (*.srm). " ) ;
puts ( " -S, --savestate=PATH Path for the save state files (*.state). " ) ;
2016-01-26 04:38:40 +00:00
puts ( " -f, --fullscreen Start the program in fullscreen regardless "
" of config settings. " ) ;
2015-07-02 22:16:46 +00:00
puts ( " -c, --config=FILE Path for config file. "
# ifdef _WIN32
2016-01-26 04:38:40 +00:00
" \n \t \t Defaults to retroarch.cfg in same directory as retroarch.exe. "
" \n \t \t If a default config is not found, the program will attempt to "
" create one. "
2015-07-02 22:16:46 +00:00
# else
2016-01-26 04:38:40 +00:00
" \n \t \t By default looks for config in $XDG_CONFIG_HOME/retroarch/ "
" retroarch.cfg, \n \t \t $HOME/.config/retroarch/retroarch.cfg, \n \t \t "
" and $HOME/.retroarch.cfg. \n \t \t If a default config is not found, "
2016-08-01 16:35:56 +00:00
" the program will attempt to create one based on the \n \t \t "
" skeleton config ( " GLOBAL_CONFIG_DIR " /retroarch.cfg). \n "
2015-07-02 22:16:46 +00:00
# endif
) ;
2015-06-12 14:18:36 +00:00
puts ( " --appendconfig=FILE \n "
2016-01-26 04:38:40 +00:00
" Extra config files are loaded in, "
" and take priority over \n "
" config selected in -c (or default). "
" Multiple configs are \n "
2015-06-12 14:18:36 +00:00
" delimited by '|'. " ) ;
2011-11-15 20:15:12 +00:00
# ifdef HAVE_DYNAMIC
2016-01-26 04:38:40 +00:00
puts ( " -L, --libretro=FILE Path to libretro implementation. "
" Overrides any config setting. " ) ;
2011-01-19 11:54:19 +00:00
# endif
2016-01-26 04:38:40 +00:00
puts ( " --subsystem=NAME Use a subsystem of the libretro core. "
" Multiple content \n "
" files are loaded as multiple arguments. "
" If a content \n "
" file is skipped, use a blank ( \" \" ) "
" command line argument. \n "
" Content must be loaded in an order "
" which depends on the \n "
" particular subsystem used. See verbose "
" log output to learn \n "
" how a particular subsystem wants content "
" to be loaded. \n " ) ;
2012-08-16 19:20:38 +00:00
2015-06-12 14:18:36 +00:00
printf ( " -N, --nodevice=PORT \n "
2016-01-26 04:38:40 +00:00
" Disconnects controller device connected "
" to PORT (1 to %d). \n " , MAX_USERS ) ;
2015-06-12 14:18:36 +00:00
printf ( " -A, --dualanalog=PORT \n "
2016-01-26 04:38:40 +00:00
" Connect a DualAnalog controller to PORT "
" (1 to %d). \n " , MAX_USERS ) ;
2015-06-12 14:18:36 +00:00
printf ( " -d, --device=PORT:ID \n "
2016-01-26 04:38:40 +00:00
" Connect a generic device into PORT of "
" the device (1 to %d). \n " , MAX_USERS ) ;
puts ( " Format is PORT:ID, where ID is a number "
" corresponding to the particular device. " ) ;
2012-08-16 19:20:38 +00:00
2015-06-12 14:18:36 +00:00
puts ( " -P, --bsvplay=FILE Playback a BSV movie file. " ) ;
2016-01-26 04:38:40 +00:00
puts ( " -R, --bsvrecord=FILE Start recording a BSV movie file from "
" the beginning. " ) ;
puts ( " --eof-exit Exit upon reaching the end of the "
" BSV movie file. " ) ;
puts ( " -M, --sram-mode=MODE SRAM handling mode. MODE can be "
" 'noload-nosave', \n "
" 'noload-save', 'load-nosave' or "
" 'load-save'. \n "
" Note: 'noload-save' implies that "
" save files *WILL BE OVERWRITTEN*. " ) ;
2011-11-20 19:19:05 +00:00
2016-09-29 19:07:10 +00:00
# ifdef HAVE_NETWORKING
2015-06-12 14:18:36 +00:00
puts ( " -H, --host Host netplay as user 1. " ) ;
puts ( " -C, --connect=HOST Connect to netplay server as user 2. " ) ;
puts ( " --port=PORT Port used to netplay. Default is 55435. " ) ;
2016-12-16 04:09:55 +00:00
puts ( " --stateless Use \" stateless \" mode for netplay " ) ;
puts ( " (requires a very fast network). " ) ;
2016-09-15 03:54:18 +00:00
puts ( " --check-frames=NUMBER \n "
" Check frames when using netplay. " ) ;
2016-09-29 19:10:35 +00:00
# if defined(HAVE_NETWORK_CMD)
2016-01-26 04:38:40 +00:00
puts ( " --command Sends a command over UDP to an already "
" running program process. " ) ;
2015-06-12 14:18:36 +00:00
puts ( " Available commands are listed if command is invalid. " ) ;
2012-06-01 13:15:06 +00:00
# endif
2011-01-07 16:59:53 +00:00
2016-09-29 19:10:35 +00:00
# endif
puts ( " --nick=NICK Picks a username (for use with netplay). "
" Not mandatory. " ) ;
2016-01-26 04:38:40 +00:00
puts ( " -r, --record=FILE Path to record video file. \n "
" Using .mkv extension is recommended. " ) ;
2015-06-12 14:18:36 +00:00
puts ( " --recordconfig Path to settings used during recording. " ) ;
puts ( " --size=WIDTHxHEIGHT \n "
" Overrides output video size when recording. " ) ;
2016-01-26 04:38:40 +00:00
puts ( " -U, --ups=FILE Specifies path for UPS patch that will be "
" applied to content. " ) ;
puts ( " --bps=FILE Specifies path for BPS patch that will be "
" applied to content. " ) ;
puts ( " --ips=FILE Specifies path for IPS patch that will be "
" applied to content. " ) ;
2015-06-12 14:18:36 +00:00
puts ( " --no-patch Disables all forms of content patching. " ) ;
2016-01-26 04:38:40 +00:00
puts ( " -D, --detach Detach program from the running console. "
" Not relevant for all platforms. " ) ;
2015-06-12 14:18:36 +00:00
puts ( " --max-frames=NUMBER \n "
2016-01-26 04:38:40 +00:00
" Runs for the specified number of frames, "
2018-08-19 03:09:40 +00:00
" then exits. " ) ;
puts ( " --max-frames-ss \n "
" Takes a screenshot at the end of max-frames. " ) ;
puts ( " --max-frames-ss-path=FILE \n "
" Path to save the screenshot to at the end of max-frames. \n " ) ;
2010-10-01 19:39:15 +00:00
}
2015-06-26 17:19:36 +00:00
# define FFMPEG_RECORD_ARG "r:"
# ifdef HAVE_DYNAMIC
# define DYNAMIC_ARG "L:"
# else
# define DYNAMIC_ARG
# endif
2016-09-29 19:07:10 +00:00
# ifdef HAVE_NETWORKING
2015-06-26 17:19:36 +00:00
# define NETPLAY_ARG "HC:F:"
# else
# define NETPLAY_ARG
# endif
# define BSV_MOVIE_ARG "P:R:M:"
2015-01-11 01:21:18 +00:00
/**
2018-03-09 22:23:34 +00:00
* retroarch_parse_input_and_config :
2015-01-11 01:21:18 +00:00
* @ argc : Count of ( commandline ) arguments .
2015-05-07 23:06:14 +00:00
* @ argv : ( Commandline ) arguments .
2015-01-11 01:21:18 +00:00
*
2018-03-09 22:23:34 +00:00
* Parses ( commandline ) arguments passed to program and loads the config file ,
* with command line options overriding the config file .
2015-01-11 01:21:18 +00:00
*
* */
2018-03-09 22:23:34 +00:00
static void retroarch_parse_input_and_config ( int argc , char * argv [ ] )
2010-05-26 19:27:37 +00:00
{
2015-06-26 17:19:36 +00:00
const char * optstring = NULL ;
2016-03-22 23:29:52 +00:00
bool explicit_menu = false ;
2019-01-06 00:16:28 +00:00
unsigned i ;
2016-10-01 04:22:57 +00:00
global_t * global = global_get_ptr ( ) ;
2011-02-18 13:49:15 +00:00
2012-01-05 20:43:55 +00:00
const struct option opts [ ] = {
2011-11-15 20:15:12 +00:00
# ifdef HAVE_DYNAMIC
2018-08-19 03:09:40 +00:00
{ " libretro " , 1 , NULL , ' L ' } ,
# endif
{ " menu " , 0 , NULL , RA_OPT_MENU } ,
{ " help " , 0 , NULL , ' h ' } ,
{ " save " , 1 , NULL , ' s ' } ,
{ " fullscreen " , 0 , NULL , ' f ' } ,
{ " record " , 1 , NULL , ' r ' } ,
{ " recordconfig " , 1 , NULL , RA_OPT_RECORDCONFIG } ,
{ " size " , 1 , NULL , RA_OPT_SIZE } ,
{ " verbose " , 0 , NULL , ' v ' } ,
{ " config " , 1 , NULL , ' c ' } ,
{ " appendconfig " , 1 , NULL , RA_OPT_APPENDCONFIG } ,
{ " nodevice " , 1 , NULL , ' N ' } ,
{ " dualanalog " , 1 , NULL , ' A ' } ,
{ " device " , 1 , NULL , ' d ' } ,
{ " savestate " , 1 , NULL , ' S ' } ,
{ " bsvplay " , 1 , NULL , ' P ' } ,
{ " bsvrecord " , 1 , NULL , ' R ' } ,
{ " sram-mode " , 1 , NULL , ' M ' } ,
2016-09-29 19:07:10 +00:00
# ifdef HAVE_NETWORKING
2018-08-19 03:09:40 +00:00
{ " host " , 0 , NULL , ' H ' } ,
{ " connect " , 1 , NULL , ' C ' } ,
{ " stateless " , 0 , NULL , RA_OPT_STATELESS } ,
{ " check-frames " , 1 , NULL , RA_OPT_CHECK_FRAMES } ,
{ " port " , 1 , NULL , RA_OPT_PORT } ,
2016-09-29 19:07:10 +00:00
# if defined(HAVE_NETWORK_CMD)
2018-08-19 03:09:40 +00:00
{ " command " , 1 , NULL , RA_OPT_COMMAND } ,
# endif
# endif
{ " nick " , 1 , NULL , RA_OPT_NICK } ,
{ " ups " , 1 , NULL , ' U ' } ,
{ " bps " , 1 , NULL , RA_OPT_BPS } ,
{ " ips " , 1 , NULL , RA_OPT_IPS } ,
{ " no-patch " , 0 , NULL , RA_OPT_NO_PATCH } ,
{ " detach " , 0 , NULL , ' D ' } ,
{ " features " , 0 , NULL , RA_OPT_FEATURES } ,
{ " subsystem " , 1 , NULL , RA_OPT_SUBSYSTEM } ,
{ " max-frames " , 1 , NULL , RA_OPT_MAX_FRAMES } ,
{ " max-frames-ss " , 0 , NULL , RA_OPT_MAX_FRAMES_SCREENSHOT } ,
{ " max-frames-ss-path " , 1 , NULL , RA_OPT_MAX_FRAMES_SCREENSHOT_PATH } ,
{ " eof-exit " , 0 , NULL , RA_OPT_EOF_EXIT } ,
{ " version " , 0 , NULL , RA_OPT_VERSION } ,
2010-10-01 19:39:15 +00:00
{ NULL , 0 , NULL , 0 }
} ;
2019-01-06 00:16:28 +00:00
/* Copy the args into a buffer so launch arguments can be reused */
2019-01-08 16:53:58 +00:00
for ( i = 0 ; i < ( unsigned ) argc ; i + + )
2019-01-06 00:16:28 +00:00
{
strlcat ( launch_arguments , argv [ i ] , sizeof ( launch_arguments ) ) ;
strlcat ( launch_arguments , " " , sizeof ( launch_arguments ) ) ;
}
string_trim_whitespace_left ( launch_arguments ) ;
2019-02-07 00:01:11 +00:00
string_trim_whitespace_right ( launch_arguments ) ;
2019-01-06 00:16:28 +00:00
2016-03-22 23:29:52 +00:00
/* Handling the core type is finicky. Based on the arguments we pass in,
* we handle it differently .
* Some current cases which track desired behavior and how it is supposed to work :
*
* Dynamically linked RA :
* . / retroarch - > CORE_TYPE_DUMMY
* . / retroarch - v - > CORE_TYPE_DUMMY + verbose
* . / retroarch - - menu - > CORE_TYPE_DUMMY
* . / retroarch - - menu - v - > CORE_TYPE_DUMMY + verbose
* . / retroarch - L contentless - core - > CORE_TYPE_PLAIN
* . / retroarch - L content - core - > CORE_TYPE_PLAIN + FAIL ( This currently crashes )
* . / retroarch [ - L content - core ] ROM - > CORE_TYPE_PLAIN
* . / retroarch < - L or ROM > - - menu - > FAIL
*
* The heuristic here seems to be that if we use the - L CLI option or
* optind < argc at the end we should set CORE_TYPE_PLAIN .
* To handle - - menu , we should ensure that CORE_TYPE_DUMMY is still set
* otherwise , fail early , since the CLI options are non - sensical .
* We could also simply ignore - - menu in this case to be more friendly with
* bogus arguments .
*/
2016-10-03 14:42:08 +00:00
if ( ! has_set_core )
2016-09-12 06:37:40 +00:00
retroarch_set_current_core_type ( CORE_TYPE_DUMMY , false ) ;
2016-05-27 19:16:25 +00:00
2016-09-30 02:31:19 +00:00
path_clear ( RARCH_PATH_SUBSYSTEM ) ;
2016-08-01 18:43:26 +00:00
2016-08-01 18:48:02 +00:00
retroarch_override_setting_free_state ( ) ;
2016-08-01 18:43:26 +00:00
2019-01-14 04:25:04 +00:00
rarch_ctl ( RARCH_CTL_USERNAME_UNSET , NULL ) ;
2019-01-12 16:58:35 +00:00
rarch_ctl ( RARCH_CTL_UNSET_UPS_PREF , NULL ) ;
rarch_ctl ( RARCH_CTL_UNSET_IPS_PREF , NULL ) ;
rarch_ctl ( RARCH_CTL_UNSET_BPS_PREF , NULL ) ;
2016-10-01 06:18:23 +00:00
* global - > name . ups = ' \0 ' ;
* global - > name . bps = ' \0 ' ;
* global - > name . ips = ' \0 ' ;
2011-11-30 15:43:09 +00:00
2017-05-15 03:06:23 +00:00
rarch_ctl ( RARCH_CTL_UNSET_OVERRIDES_ACTIVE , NULL ) ;
2014-09-02 15:05:15 +00:00
2016-05-09 05:24:28 +00:00
/* Make sure we can call retroarch_parse_input several times ... */
2015-06-26 17:19:36 +00:00
optind = 0 ;
2016-03-10 22:36:46 +00:00
optstring = " hs:fvS:A:c:U:DN:d: "
2016-01-26 04:38:40 +00:00
BSV_MOVIE_ARG NETPLAY_ARG DYNAMIC_ARG FFMPEG_RECORD_ARG ;
2013-01-13 03:12:10 +00:00
2019-01-03 20:46:29 +00:00
# ifdef ORBIS
argv = & ( argv [ 2 ] ) ;
argc = argc - 2 ;
# endif
2016-08-01 16:35:56 +00:00
# ifndef HAVE_MENU
if ( argc = = 1 )
{
2016-11-08 14:17:02 +00:00
printf ( " %s \n " , msg_hash_to_str ( MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN ) ) ;
2016-08-01 16:35:56 +00:00
retroarch_print_help ( argv [ 0 ] ) ;
exit ( 0 ) ;
}
# endif
2018-03-09 22:23:34 +00:00
/* First pass: Read the config file path and any directory overrides, so
* they ' re in place when we load the config */
2019-01-07 03:03:16 +00:00
if ( argc )
2010-05-29 13:21:30 +00:00
{
2019-01-07 03:03:16 +00:00
for ( ; ; )
{
int c = getopt_long ( argc , argv , optstring , opts , NULL ) ;
2015-06-26 18:35:02 +00:00
2016-06-28 02:23:57 +00:00
#if 0
2019-01-07 03:03:16 +00:00
fprintf ( stderr , " c is: %c (%d), optarg is: [%s] \n " , c , c , string_is_empty ( optarg ) ? " " : optarg ) ;
2016-06-28 02:23:57 +00:00
# endif
2019-01-07 03:03:16 +00:00
if ( c = = - 1 )
break ;
2010-10-01 19:39:15 +00:00
2019-01-07 03:03:16 +00:00
switch ( c )
{
case ' h ' :
retroarch_print_help ( argv [ 0 ] ) ;
exit ( 0 ) ;
2010-10-01 19:39:15 +00:00
2019-01-07 03:03:16 +00:00
case ' c ' :
RARCH_LOG ( " Set config file to : %s \n " , optarg ) ;
path_set ( RARCH_PATH_CONFIG , optarg ) ;
break ;
2018-03-09 22:23:34 +00:00
2019-01-07 03:03:16 +00:00
case RA_OPT_APPENDCONFIG :
path_set ( RARCH_PATH_CONFIG_APPEND , optarg ) ;
break ;
2018-03-20 22:48:51 +00:00
2019-01-07 03:03:16 +00:00
case ' s ' :
strlcpy ( global - > name . savefile , optarg ,
sizeof ( global - > name . savefile ) ) ;
retroarch_override_setting_set (
RARCH_OVERRIDE_SETTING_SAVE_PATH , NULL ) ;
break ;
2018-03-09 22:23:34 +00:00
2019-01-07 03:03:16 +00:00
case ' S ' :
strlcpy ( global - > name . savestate , optarg ,
sizeof ( global - > name . savestate ) ) ;
retroarch_override_setting_set (
RARCH_OVERRIDE_SETTING_STATE_PATH , NULL ) ;
break ;
2018-03-09 22:23:34 +00:00
2019-01-07 03:03:16 +00:00
/* Must handle '?' otherwise you get an infinite loop */
case ' ? ' :
retroarch_print_help ( argv [ 0 ] ) ;
retroarch_fail ( 1 , " retroarch_parse_input() " ) ;
break ;
/* All other arguments are handled in the second pass */
}
2018-03-09 22:23:34 +00:00
}
}
/* Load the config file now that we know what it is */
config_load ( ) ;
/* Second pass: All other arguments override the config file */
optind = 1 ;
2019-01-07 03:03:16 +00:00
if ( argc )
2018-03-09 22:23:34 +00:00
{
2019-01-07 03:03:16 +00:00
for ( ; ; )
2018-03-09 22:23:34 +00:00
{
2019-01-07 03:03:16 +00:00
int c = getopt_long ( argc , argv , optstring , opts , NULL ) ;
2011-01-10 15:53:37 +00:00
2019-01-07 03:03:16 +00:00
if ( c = = - 1 )
break ;
2017-01-17 18:59:33 +00:00
2019-01-07 03:03:16 +00:00
switch ( c )
{
case ' d ' :
2017-05-29 12:58:30 +00:00
{
2019-01-07 03:03:16 +00:00
unsigned new_port ;
unsigned id = 0 ;
struct string_list * list = string_split ( optarg , " : " ) ;
int port = 0 ;
2016-10-01 04:22:57 +00:00
2019-01-07 03:03:16 +00:00
if ( list & & list - > size = = 2 )
{
port = ( int ) strtol ( list - > elems [ 0 ] . data , NULL , 0 ) ;
id = ( unsigned ) strtoul ( list - > elems [ 1 ] . data , NULL , 0 ) ;
}
string_list_free ( list ) ;
2017-05-29 12:58:30 +00:00
2019-01-07 03:03:16 +00:00
if ( port < 1 | | port > MAX_USERS )
{
RARCH_ERR ( " %s \n " , msg_hash_to_str ( MSG_VALUE_CONNECT_DEVICE_FROM_A_VALID_PORT ) ) ;
retroarch_print_help ( argv [ 0 ] ) ;
retroarch_fail ( 1 , " retroarch_parse_input() " ) ;
}
new_port = port - 1 ;
2014-04-04 12:58:42 +00:00
2019-01-07 03:03:16 +00:00
input_config_set_device ( new_port , id ) ;
2016-10-01 04:22:57 +00:00
2019-01-07 03:03:16 +00:00
retroarch_override_setting_set (
RARCH_OVERRIDE_SETTING_LIBRETRO_DEVICE , & new_port ) ;
2017-05-29 12:58:30 +00:00
}
2019-01-07 03:03:16 +00:00
break ;
2017-05-29 12:58:30 +00:00
2019-01-07 03:03:16 +00:00
case ' A ' :
2017-05-29 12:58:30 +00:00
{
2019-01-07 03:03:16 +00:00
unsigned new_port ;
int port = ( int ) strtol ( optarg , NULL , 0 ) ;
2012-08-16 19:20:38 +00:00
2019-01-07 03:03:16 +00:00
if ( port < 1 | | port > MAX_USERS )
{
RARCH_ERR ( " Connect dualanalog to a valid port. \n " ) ;
retroarch_print_help ( argv [ 0 ] ) ;
retroarch_fail ( 1 , " retroarch_parse_input() " ) ;
}
new_port = port - 1 ;
2011-07-09 06:37:08 +00:00
2019-01-07 03:03:16 +00:00
input_config_set_device ( new_port , RETRO_DEVICE_ANALOG ) ;
retroarch_override_setting_set (
RARCH_OVERRIDE_SETTING_LIBRETRO_DEVICE , & new_port ) ;
2017-05-29 12:58:30 +00:00
}
2019-01-07 03:03:16 +00:00
break ;
2010-10-01 20:10:28 +00:00
2019-01-07 03:03:16 +00:00
case ' f ' :
rarch_force_fullscreen = true ;
break ;
2017-05-29 12:58:30 +00:00
2019-01-07 03:03:16 +00:00
case ' v ' :
verbosity_enable ( ) ;
2016-10-01 04:22:57 +00:00
retroarch_override_setting_set (
2019-01-07 03:03:16 +00:00
RARCH_OVERRIDE_SETTING_VERBOSITY , NULL ) ;
break ;
2011-01-05 19:07:55 +00:00
2019-01-07 03:03:16 +00:00
case ' N ' :
2017-05-29 12:58:30 +00:00
{
2019-01-07 03:03:16 +00:00
unsigned new_port ;
int port = ( int ) strtol ( optarg , NULL , 0 ) ;
2017-01-17 18:59:33 +00:00
2019-01-07 03:03:16 +00:00
if ( port < 1 | | port > MAX_USERS )
{
RARCH_ERR ( " %s \n " ,
msg_hash_to_str ( MSG_DISCONNECT_DEVICE_FROM_A_VALID_PORT ) ) ;
retroarch_print_help ( argv [ 0 ] ) ;
retroarch_fail ( 1 , " retroarch_parse_input() " ) ;
}
new_port = port - 1 ;
input_config_set_device ( port - 1 , RETRO_DEVICE_NONE ) ;
retroarch_override_setting_set (
RARCH_OVERRIDE_SETTING_LIBRETRO_DEVICE , & new_port ) ;
2017-05-29 12:58:30 +00:00
}
2019-01-07 03:03:16 +00:00
break ;
case ' r ' :
strlcpy ( global - > record . path , optarg ,
sizeof ( global - > record . path ) ) ;
if ( recording_is_enabled ( ) )
recording_set_state ( true ) ;
break ;
# ifdef HAVE_DYNAMIC
case ' L ' :
if ( path_is_directory ( optarg ) )
{
settings_t * settings = config_get_ptr ( ) ;
2018-04-30 18:33:05 +00:00
2019-01-07 03:03:16 +00:00
path_clear ( RARCH_PATH_CORE ) ;
strlcpy ( settings - > paths . directory_libretro , optarg ,
sizeof ( settings - > paths . directory_libretro ) ) ;
2018-04-30 18:33:05 +00:00
2019-01-07 03:03:16 +00:00
retroarch_override_setting_set ( RARCH_OVERRIDE_SETTING_LIBRETRO , NULL ) ;
retroarch_override_setting_set ( RARCH_OVERRIDE_SETTING_LIBRETRO_DIRECTORY , NULL ) ;
RARCH_WARN ( " Using old --libretro behavior. "
" Setting libretro_directory to \" %s \" instead. \n " ,
optarg ) ;
}
else if ( filestream_exists ( optarg ) )
{
2016-03-22 23:46:15 +00:00
2019-01-07 03:03:16 +00:00
rarch_ctl ( RARCH_CTL_SET_LIBRETRO_PATH , optarg ) ;
retroarch_override_setting_set ( RARCH_OVERRIDE_SETTING_LIBRETRO , NULL ) ;
2016-03-22 23:29:52 +00:00
2019-01-07 03:03:16 +00:00
/* We requested explicit core, so use PLAIN core type. */
retroarch_set_current_core_type ( CORE_TYPE_PLAIN , false ) ;
}
else
{
RARCH_WARN ( " --libretro argument \" %s \" is neither a file nor directory. Ignoring. \n " ,
optarg ) ;
}
2015-12-01 00:25:36 +00:00
2019-01-07 03:03:16 +00:00
break ;
# endif
case ' P ' :
case ' R ' :
bsv_movie_set_start_path ( optarg ) ;
2015-12-01 00:25:36 +00:00
2019-01-07 03:03:16 +00:00
if ( c = = ' P ' )
bsv_movie_ctl ( BSV_MOVIE_CTL_SET_START_PLAYBACK , NULL ) ;
else
bsv_movie_ctl ( BSV_MOVIE_CTL_UNSET_START_PLAYBACK , NULL ) ;
2011-11-18 17:03:24 +00:00
2019-01-07 03:03:16 +00:00
if ( c = = ' R ' )
bsv_movie_ctl ( BSV_MOVIE_CTL_SET_START_RECORDING , NULL ) ;
else
bsv_movie_ctl ( BSV_MOVIE_CTL_UNSET_START_RECORDING , NULL ) ;
break ;
2011-02-02 11:10:27 +00:00
2019-01-07 03:03:16 +00:00
case ' M ' :
if ( string_is_equal ( optarg , " noload-nosave " ) )
{
rarch_is_sram_load_disabled = true ;
rarch_is_sram_save_disabled = true ;
}
else if ( string_is_equal ( optarg , " noload-save " ) )
rarch_is_sram_load_disabled = true ;
else if ( string_is_equal ( optarg , " load-nosave " ) )
rarch_is_sram_save_disabled = true ;
else if ( string_is_not_equal ( optarg , " load-save " ) )
2016-10-01 04:22:57 +00:00
{
2019-01-07 03:03:16 +00:00
RARCH_ERR ( " Invalid argument in --sram-mode. \n " ) ;
2016-10-01 04:22:57 +00:00
retroarch_print_help ( argv [ 0 ] ) ;
retroarch_fail ( 1 , " retroarch_parse_input() " ) ;
}
2019-01-07 03:03:16 +00:00
break ;
2011-02-13 15:40:24 +00:00
2019-01-07 03:03:16 +00:00
# ifdef HAVE_NETWORKING
case ' H ' :
2017-01-17 18:59:33 +00:00
retroarch_override_setting_set (
RARCH_OVERRIDE_SETTING_NETPLAY_MODE , NULL ) ;
2019-01-07 03:03:16 +00:00
netplay_driver_ctl ( RARCH_NETPLAY_CTL_ENABLE_SERVER , NULL ) ;
break ;
2016-09-29 19:10:35 +00:00
2019-01-07 03:03:16 +00:00
case ' C ' :
{
settings_t * settings = config_get_ptr ( ) ;
retroarch_override_setting_set (
RARCH_OVERRIDE_SETTING_NETPLAY_MODE , NULL ) ;
retroarch_override_setting_set (
RARCH_OVERRIDE_SETTING_NETPLAY_IP_ADDRESS , NULL ) ;
netplay_driver_ctl ( RARCH_NETPLAY_CTL_ENABLE_CLIENT , NULL ) ;
strlcpy ( settings - > paths . netplay_server , optarg ,
sizeof ( settings - > paths . netplay_server ) ) ;
}
break ;
2011-02-15 14:32:26 +00:00
2019-01-07 03:03:16 +00:00
case RA_OPT_STATELESS :
{
settings_t * settings = config_get_ptr ( ) ;
2015-06-30 20:43:41 +00:00
2019-01-07 03:03:16 +00:00
configuration_set_bool ( settings ,
settings - > bools . netplay_stateless_mode , true ) ;
2011-04-23 12:47:50 +00:00
2019-01-07 03:03:16 +00:00
retroarch_override_setting_set (
RARCH_OVERRIDE_SETTING_NETPLAY_STATELESS_MODE , NULL ) ;
}
break ;
2015-06-30 20:43:41 +00:00
2019-01-07 03:03:16 +00:00
case RA_OPT_CHECK_FRAMES :
{
settings_t * settings = config_get_ptr ( ) ;
retroarch_override_setting_set (
RARCH_OVERRIDE_SETTING_NETPLAY_CHECK_FRAMES , NULL ) ;
2015-06-30 20:43:41 +00:00
2019-01-07 03:03:16 +00:00
configuration_set_int ( settings ,
settings - > ints . netplay_check_frames ,
( int ) strtoul ( optarg , NULL , 0 ) ) ;
}
break ;
2015-10-20 00:43:21 +00:00
2019-01-07 03:03:16 +00:00
case RA_OPT_PORT :
{
settings_t * settings = config_get_ptr ( ) ;
retroarch_override_setting_set (
RARCH_OVERRIDE_SETTING_NETPLAY_IP_PORT , NULL ) ;
configuration_set_uint ( settings ,
settings - > uints . netplay_port ,
( int ) strtoul ( optarg , NULL , 0 ) ) ;
}
break ;
2013-04-14 14:24:19 +00:00
2019-01-07 03:03:16 +00:00
# if defined(HAVE_NETWORK_CMD)
case RA_OPT_COMMAND :
# ifdef HAVE_COMMAND
if ( command_network_send ( ( const char * ) optarg ) )
exit ( 0 ) ;
else
retroarch_fail ( 1 , " network_cmd_send() " ) ;
# endif
break ;
# endif
# endif
case RA_OPT_BPS :
strlcpy ( global - > name . bps , optarg ,
sizeof ( global - > name . bps ) ) ;
rarch_bps_pref = true ;
retroarch_override_setting_set ( RARCH_OVERRIDE_SETTING_BPS_PREF , NULL ) ;
break ;
case ' U ' :
strlcpy ( global - > name . ups , optarg ,
sizeof ( global - > name . ups ) ) ;
rarch_ups_pref = true ;
retroarch_override_setting_set ( RARCH_OVERRIDE_SETTING_UPS_PREF , NULL ) ;
break ;
case RA_OPT_IPS :
strlcpy ( global - > name . ips , optarg ,
sizeof ( global - > name . ips ) ) ;
rarch_ips_pref = true ;
retroarch_override_setting_set ( RARCH_OVERRIDE_SETTING_IPS_PREF , NULL ) ;
break ;
case RA_OPT_NO_PATCH :
rarch_ctl ( RARCH_CTL_SET_PATCH_BLOCKED , NULL ) ;
break ;
case ' D ' :
frontend_driver_detach_console ( ) ;
break ;
case RA_OPT_MENU :
explicit_menu = true ;
break ;
case RA_OPT_NICK :
{
settings_t * settings = config_get_ptr ( ) ;
2017-05-12 01:39:37 +00:00
2019-01-14 04:25:04 +00:00
rarch_ctl ( RARCH_CTL_USERNAME_SET , NULL ) ;
2017-05-12 01:39:37 +00:00
2019-01-07 03:03:16 +00:00
strlcpy ( settings - > paths . username , optarg ,
sizeof ( settings - > paths . username ) ) ;
}
break ;
2016-09-29 19:07:10 +00:00
2019-01-07 03:03:16 +00:00
case RA_OPT_SIZE :
{
2019-02-12 05:04:52 +00:00
unsigned recording_width = 0 ;
unsigned recording_height = 0 ;
recording_driver_get_size ( & recording_width ,
& recording_height ) ;
if ( sscanf ( optarg , " %ux%u " ,
& recording_width ,
& recording_height ) ! = 2 )
{
RARCH_ERR ( " Wrong format for --size. \n " ) ;
retroarch_print_help ( argv [ 0 ] ) ;
retroarch_fail ( 1 , " retroarch_parse_input() " ) ;
}
2019-01-07 03:03:16 +00:00
}
break ;
2011-02-18 13:49:15 +00:00
2019-01-07 03:03:16 +00:00
case RA_OPT_RECORDCONFIG :
strlcpy ( global - > record . config , optarg ,
sizeof ( global - > record . config ) ) ;
break ;
2015-06-30 20:36:17 +00:00
2019-01-07 03:03:16 +00:00
case RA_OPT_MAX_FRAMES :
runloop_max_frames = ( unsigned ) strtoul ( optarg , NULL , 10 ) ;
break ;
2015-06-30 20:36:17 +00:00
2019-01-07 03:03:16 +00:00
case RA_OPT_MAX_FRAMES_SCREENSHOT :
runloop_max_frames_screenshot = true ;
break ;
2018-08-19 03:09:40 +00:00
2019-01-07 03:03:16 +00:00
case RA_OPT_MAX_FRAMES_SCREENSHOT_PATH :
strlcpy ( runloop_max_frames_screenshot_path , optarg , sizeof ( runloop_max_frames_screenshot_path ) ) ;
break ;
2018-08-19 03:09:40 +00:00
2019-01-07 03:03:16 +00:00
case RA_OPT_SUBSYSTEM :
path_set ( RARCH_PATH_SUBSYSTEM , optarg ) ;
break ;
2015-06-30 20:36:17 +00:00
2019-01-07 03:03:16 +00:00
case RA_OPT_FEATURES :
retroarch_print_features ( ) ;
exit ( 0 ) ;
2015-06-30 20:36:17 +00:00
2019-01-07 03:03:16 +00:00
case RA_OPT_EOF_EXIT :
bsv_movie_ctl ( BSV_MOVIE_CTL_SET_END_EOF , NULL ) ;
break ;
2015-06-30 20:36:17 +00:00
2019-01-07 03:03:16 +00:00
case RA_OPT_VERSION :
retroarch_print_version ( ) ;
exit ( 0 ) ;
2010-10-01 19:39:15 +00:00
2019-01-07 03:03:16 +00:00
case ' c ' :
case ' h ' :
case RA_OPT_APPENDCONFIG :
case ' s ' :
case ' S ' :
break ; /* Handled in the first pass */
2018-03-09 22:23:34 +00:00
2019-01-07 03:03:16 +00:00
case ' ? ' :
retroarch_print_help ( argv [ 0 ] ) ;
retroarch_fail ( 1 , " retroarch_parse_input() " ) ;
2015-06-30 20:39:13 +00:00
2019-01-07 03:03:16 +00:00
default :
RARCH_ERR ( " %s \n " , msg_hash_to_str ( MSG_ERROR_PARSING_ARGUMENTS ) ) ;
retroarch_fail ( 1 , " retroarch_parse_input() " ) ;
}
2010-10-01 19:39:15 +00:00
}
2010-05-29 13:21:30 +00:00
}
2017-07-05 01:46:22 +00:00
2019-03-05 22:34:05 +00:00
if ( verbosity_is_enabled ( ) )
2019-03-21 16:56:24 +00:00
rarch_log_file_init ( ) ;
2019-03-05 22:34:05 +00:00
2017-01-29 04:06:14 +00:00
# ifdef HAVE_GIT_VERSION
2017-07-05 01:46:22 +00:00
RARCH_LOG ( " RetroArch %s (Git %s) \n " ,
2017-05-29 12:58:30 +00:00
PACKAGE_VERSION , retroarch_git_version ) ;
2017-01-29 04:06:14 +00:00
# endif
2010-05-29 13:21:30 +00:00
2016-04-05 21:21:55 +00:00
if ( explicit_menu )
2013-04-14 14:24:19 +00:00
{
2016-04-05 21:21:55 +00:00
if ( optind < argc )
{
RARCH_ERR ( " --menu was used, but content file was passed as well. \n " ) ;
2016-05-09 05:24:28 +00:00
retroarch_fail ( 1 , " retroarch_parse_input() " ) ;
2016-04-05 21:21:55 +00:00
}
2016-09-12 06:37:40 +00:00
# ifdef HAVE_DYNAMIC
2016-04-05 21:21:55 +00:00
else
{
2017-07-05 01:46:22 +00:00
/* Allow stray -L arguments to go through to workaround cases
2016-09-17 12:23:44 +00:00
* where it ' s used as " config file " .
*
2017-07-05 01:46:22 +00:00
* This seems to still be the case for Android , which
2016-09-17 12:23:44 +00:00
* should be properly fixed . */
2016-05-27 19:16:25 +00:00
retroarch_set_current_core_type ( CORE_TYPE_DUMMY , false ) ;
2016-04-05 21:21:55 +00:00
}
2016-09-12 06:37:40 +00:00
# endif
2013-04-14 14:24:19 +00:00
}
2016-03-22 23:29:52 +00:00
2016-09-30 02:43:16 +00:00
if ( path_is_empty ( RARCH_PATH_SUBSYSTEM ) & & optind < argc )
2016-02-15 20:30:11 +00:00
{
2016-03-22 23:29:52 +00:00
/* We requested explicit ROM, so use PLAIN core type. */
2016-05-27 19:16:25 +00:00
retroarch_set_current_core_type ( CORE_TYPE_PLAIN , false ) ;
2016-09-30 02:19:42 +00:00
path_set ( RARCH_PATH_NAMES , ( const char * ) argv [ optind ] ) ;
2016-02-15 20:30:11 +00:00
}
2016-09-30 02:43:16 +00:00
else if ( ! path_is_empty ( RARCH_PATH_SUBSYSTEM ) & & optind < argc )
2016-03-22 23:29:52 +00:00
{
/* We requested explicit ROM, so use PLAIN core type. */
2016-05-27 19:16:25 +00:00
retroarch_set_current_core_type ( CORE_TYPE_PLAIN , false ) ;
2016-09-17 10:19:17 +00:00
path_set_special ( argv + optind , argc - optind ) ;
2016-03-22 23:29:52 +00:00
}
2015-06-23 04:44:29 +00:00
2014-08-20 15:18:43 +00:00
/* Copy SRM/state dirs used, so they can be reused on reentrancy. */
2016-10-01 04:05:08 +00:00
if ( retroarch_override_setting_is_set ( RARCH_OVERRIDE_SETTING_SAVE_PATH , NULL ) & &
2016-10-01 06:18:23 +00:00
path_is_directory ( global - > name . savefile ) )
2016-10-03 06:20:33 +00:00
dir_set ( RARCH_DIR_SAVEFILE , global - > name . savefile ) ;
2016-10-01 06:18:23 +00:00
2016-10-01 06:24:02 +00:00
if ( retroarch_override_setting_is_set ( RARCH_OVERRIDE_SETTING_STATE_PATH , NULL ) & &
2016-10-01 06:18:23 +00:00
path_is_directory ( global - > name . savestate ) )
2016-10-03 06:20:33 +00:00
dir_set ( RARCH_DIR_SAVESTATE , global - > name . savestate ) ;
2010-10-01 19:39:15 +00:00
}
2010-08-15 08:02:04 +00:00
2019-02-27 15:47:39 +00:00
static bool drivers_set_active ( void )
2011-08-26 15:32:04 +00:00
{
2016-05-08 12:00:51 +00:00
video_driver_set_active ( ) ;
2016-05-08 16:24:25 +00:00
audio_driver_set_active ( ) ;
2015-03-22 06:28:45 +00:00
return true ;
2013-09-22 09:08:09 +00:00
}
2013-04-27 10:32:03 +00:00
2016-05-09 05:09:26 +00:00
bool retroarch_validate_game_options ( char * s , size_t len , bool mkdir )
2016-01-26 01:24:59 +00:00
{
2018-02-04 22:02:52 +00:00
char * core_path = NULL ;
char * config_directory = NULL ;
2017-09-09 04:21:27 +00:00
size_t str_size = PATH_MAX_LENGTH * sizeof ( char ) ;
2017-05-30 14:57:29 +00:00
const char * core_name = runloop_system . info . library_name ;
2017-05-20 17:24:21 +00:00
const char * game_name = path_basename ( path_get ( RARCH_PATH_BASENAME ) ) ;
2016-01-26 01:24:59 +00:00
if ( string_is_empty ( core_name ) | | string_is_empty ( game_name ) )
2018-02-04 22:02:52 +00:00
return false ;
2016-01-26 01:24:59 +00:00
2018-10-29 06:38:26 +00:00
core_path = ( char * ) malloc ( str_size ) ;
config_directory = ( char * ) malloc ( str_size ) ;
2017-05-20 17:24:21 +00:00
config_directory [ 0 ] = core_path [ 0 ] = ' \0 ' ;
2017-01-17 19:07:41 +00:00
fill_pathname_application_special ( config_directory ,
2017-09-09 04:21:27 +00:00
str_size , APPLICATION_SPECIAL_DIRECTORY_CONFIG ) ;
2016-01-26 01:24:59 +00:00
/* Concatenate strings into full paths for game_path */
2016-06-30 02:59:57 +00:00
fill_pathname_join_special_ext ( s ,
config_directory , core_name , game_name ,
file_path_str ( FILE_PATH_OPT_EXTENSION ) ,
len ) ;
2016-01-26 01:24:59 +00:00
fill_pathname_join ( core_path ,
2017-09-09 04:21:27 +00:00
config_directory , core_name , str_size ) ;
2016-02-08 05:07:41 +00:00
if ( ! path_is_directory ( core_path ) & & mkdir )
2016-01-26 01:24:59 +00:00
path_mkdir ( core_path ) ;
2017-09-09 04:21:27 +00:00
free ( core_path ) ;
free ( config_directory ) ;
2016-01-26 01:24:59 +00:00
return true ;
}
2014-10-05 17:13:03 +00:00
2016-05-11 19:48:30 +00:00
/* Validates CPU features for given processor architecture.
* Make sure we haven ' t compiled for something we cannot run .
* Ideally , code would get swapped out depending on CPU support ,
* but this will do for now . */
static void retroarch_validate_cpu_features ( void )
{
uint64_t cpu = cpu_features_get ( ) ;
( void ) cpu ;
2019-02-23 21:50:36 +00:00
# ifdef __MMX__
if ( ! ( cpu & RETRO_SIMD_MMX ) )
FAIL_CPU ( " MMX " ) ;
# endif
2016-05-11 19:48:30 +00:00
# ifdef __SSE__
if ( ! ( cpu & RETRO_SIMD_SSE ) )
FAIL_CPU ( " SSE " ) ;
# endif
# ifdef __SSE2__
if ( ! ( cpu & RETRO_SIMD_SSE2 ) )
FAIL_CPU ( " SSE2 " ) ;
# endif
# ifdef __AVX__
if ( ! ( cpu & RETRO_SIMD_AVX ) )
FAIL_CPU ( " AVX " ) ;
# endif
}
2016-09-11 17:57:06 +00:00
static void retroarch_main_init_media ( void )
{
2018-12-11 01:03:03 +00:00
settings_t * settings = config_get_ptr ( ) ;
2017-04-28 11:43:47 +00:00
const char * fullpath = path_get ( RARCH_PATH_CONTENT ) ;
2017-04-28 19:47:26 +00:00
bool builtin_imageviewer = false ;
bool builtin_mediaplayer = false ;
2016-09-11 17:57:06 +00:00
if ( ! settings )
return ;
2017-04-28 19:47:26 +00:00
builtin_imageviewer = settings - > bools . multimedia_builtin_imageviewer_enable ;
builtin_mediaplayer = settings - > bools . multimedia_builtin_mediaplayer_enable ;
2017-04-28 11:43:47 +00:00
if ( ! builtin_mediaplayer & & ! builtin_imageviewer )
2016-09-11 17:57:06 +00:00
return ;
if ( string_is_empty ( fullpath ) )
return ;
2016-09-17 10:56:19 +00:00
switch ( path_is_media_type ( fullpath ) )
2016-09-11 17:57:06 +00:00
{
case RARCH_CONTENT_MOVIE :
case RARCH_CONTENT_MUSIC :
2017-04-28 11:43:47 +00:00
if ( builtin_mediaplayer )
2016-09-11 17:57:06 +00:00
{
2018-06-20 02:29:31 +00:00
/* TODO/FIXME - it needs to become possible to switch between FFmpeg and MPV at runtime */
# if defined(HAVE_MPV)
retroarch_override_setting_set ( RARCH_OVERRIDE_SETTING_LIBRETRO , NULL ) ;
retroarch_set_current_core_type ( CORE_TYPE_MPV , false ) ;
# elif defined(HAVE_FFMPEG)
2016-10-01 03:51:03 +00:00
retroarch_override_setting_set ( RARCH_OVERRIDE_SETTING_LIBRETRO , NULL ) ;
2016-09-11 17:57:06 +00:00
retroarch_set_current_core_type ( CORE_TYPE_FFMPEG , false ) ;
# endif
}
break ;
# ifdef HAVE_IMAGEVIEWER
case RARCH_CONTENT_IMAGE :
2017-04-28 11:43:47 +00:00
if ( builtin_imageviewer )
2016-09-11 17:57:06 +00:00
{
2016-10-01 03:51:03 +00:00
retroarch_override_setting_set ( RARCH_OVERRIDE_SETTING_LIBRETRO , NULL ) ;
2016-09-11 17:57:06 +00:00
retroarch_set_current_core_type ( CORE_TYPE_IMAGEVIEWER , false ) ;
}
break ;
2019-01-05 23:33:29 +00:00
# endif
# ifdef HAVE_EASTEREGG
case RARCH_CONTENT_GONG :
retroarch_override_setting_set ( RARCH_OVERRIDE_SETTING_LIBRETRO , NULL ) ;
retroarch_set_current_core_type ( CORE_TYPE_GONG , false ) ;
break ;
2016-09-11 17:57:06 +00:00
# endif
default :
break ;
}
}
2015-01-11 01:21:18 +00:00
/**
2016-05-09 05:09:26 +00:00
* retroarch_main_init :
2015-01-11 01:21:18 +00:00
* @ argc : Count of ( commandline ) arguments .
2015-10-20 00:43:21 +00:00
* @ argv : ( Commandline ) arguments .
2015-01-11 01:21:18 +00:00
*
2015-06-30 13:26:14 +00:00
* Initializes the program .
2015-01-11 01:21:18 +00:00
*
2017-12-29 14:31:17 +00:00
* Returns : true on success , otherwise false if there was an error .
2015-01-11 01:21:18 +00:00
* */
2016-05-11 18:50:34 +00:00
bool retroarch_main_init ( int argc , char * argv [ ] )
2012-01-14 15:08:54 +00:00
{
2016-07-19 04:33:56 +00:00
bool init_failed = false ;
2018-09-15 22:44:46 +00:00
global_t * global = global_get_ptr ( ) ;
2016-07-19 04:20:19 +00:00
2018-12-11 01:03:03 +00:00
# if defined(DEBUG) && defined(HAVE_DRMINGW)
char log_file_name [ 128 ] ;
# endif
2019-02-27 15:47:39 +00:00
drivers_set_active ( ) ;
2011-12-25 20:39:58 +00:00
2016-05-16 06:46:06 +00:00
if ( setjmp ( error_sjlj_context ) > 0 )
2012-01-14 15:08:54 +00:00
{
2016-06-20 01:54:42 +00:00
RARCH_ERR ( " %s: \" %s \" \n " ,
msg_hash_to_str ( MSG_FATAL_ERROR_RECEIVED_IN ) , error_string ) ;
2016-05-11 18:50:34 +00:00
return false ;
2012-01-14 15:08:54 +00:00
}
2015-11-30 18:30:05 +00:00
2017-05-08 01:59:02 +00:00
rarch_error_on_init = true ;
2019-03-21 16:56:24 +00:00
/* Have to initialise non-file logging once at the start... */
retro_main_log_file_init ( NULL , false ) ;
2018-03-09 22:23:34 +00:00
retroarch_parse_input_and_config ( argc , argv ) ;
2012-05-03 22:14:42 +00:00
2016-05-31 02:42:04 +00:00
if ( verbosity_is_enabled ( ) )
2011-12-25 20:39:58 +00:00
{
2017-09-09 04:21:27 +00:00
char str [ 128 ] ;
2019-02-23 21:50:36 +00:00
const char * cpu_model = NULL ;
2016-10-21 03:57:40 +00:00
str [ 0 ] = ' \0 ' ;
2015-04-16 18:17:05 +00:00
2019-02-23 21:50:36 +00:00
cpu_model = frontend_driver_get_cpu_model_name ( ) ;
2016-05-25 02:40:44 +00:00
RARCH_LOG_OUTPUT ( " === Build ======================================= \n " ) ;
2019-02-23 21:50:36 +00:00
if ( ! string_is_empty ( cpu_model ) )
RARCH_LOG_OUTPUT ( " CPU Model Name: %s \n " , cpu_model ) ;
2016-05-09 05:09:26 +00:00
retroarch_get_capabilities ( RARCH_CAPABILITIES_CPU , str , sizeof ( str ) ) ;
2019-03-21 16:56:24 +00:00
RARCH_LOG_OUTPUT ( " %s: %s \n " , msg_hash_to_str ( MSG_CAPABILITIES ) , str ) ;
RARCH_LOG_OUTPUT ( " Built: %s \n " , __DATE__ ) ;
2014-01-11 17:51:42 +00:00
RARCH_LOG_OUTPUT ( " Version: %s \n " , PACKAGE_VERSION ) ;
# ifdef HAVE_GIT_VERSION
2016-05-11 18:44:24 +00:00
RARCH_LOG_OUTPUT ( " Git: %s \n " , retroarch_git_version ) ;
2014-01-11 17:51:42 +00:00
# endif
2012-10-16 11:57:35 +00:00
RARCH_LOG_OUTPUT ( " ================================================= \n " ) ;
2011-12-25 20:39:58 +00:00
}
2018-12-11 01:03:03 +00:00
# if defined(DEBUG) && defined(HAVE_DRMINGW)
RARCH_LOG ( " Initializing Dr.MingW Exception handler \n " ) ;
fill_str_dated_filename ( log_file_name , " crash " ,
" log " , sizeof ( log_file_name ) ) ;
ExcHndlInit ( ) ;
ExcHndlSetLogFileNameA ( log_file_name ) ;
# endif
2016-05-11 19:48:30 +00:00
retroarch_validate_cpu_features ( ) ;
2016-02-09 16:41:19 +00:00
2017-05-15 03:06:23 +00:00
rarch_ctl ( RARCH_CTL_TASK_INIT , NULL ) ;
2010-12-30 12:54:49 +00:00
2016-09-11 17:57:06 +00:00
retroarch_main_init_media ( ) ;
2016-07-19 04:20:19 +00:00
2019-02-27 15:47:39 +00:00
/* Pre-initialize all drivers
* Attempts to find a default driver for
* all driver types .
*/
audio_driver_find_driver ( ) ;
video_driver_find_driver ( ) ;
input_driver_find_driver ( ) ;
camera_driver_ctl ( RARCH_CAMERA_CTL_FIND_DRIVER , NULL ) ;
wifi_driver_ctl ( RARCH_WIFI_CTL_FIND_DRIVER , NULL ) ;
find_location_driver ( ) ;
# ifdef HAVE_MENU
menu_driver_ctl ( RARCH_MENU_CTL_FIND_DRIVER , NULL ) ;
# endif
2016-07-19 04:20:19 +00:00
2016-07-19 04:27:46 +00:00
/* Attempt to initialize core */
2016-10-03 14:42:08 +00:00
if ( has_set_core )
2016-05-27 19:16:25 +00:00
{
2016-10-03 14:42:08 +00:00
has_set_core = false ;
2016-05-27 19:16:25 +00:00
if ( ! command_event ( CMD_EVENT_CORE_INIT , & explicit_current_core_type ) )
2016-07-19 04:27:46 +00:00
init_failed = true ;
2016-05-27 19:16:25 +00:00
}
else if ( ! command_event ( CMD_EVENT_CORE_INIT , & current_core_type ) )
2016-07-19 04:27:46 +00:00
init_failed = true ;
/* Handle core initialization failure */
2016-07-19 04:33:56 +00:00
if ( init_failed )
{
2016-07-19 04:27:46 +00:00
/* Check if menu was active prior to core initialization */
2019-01-09 16:39:31 +00:00
if ( ! content_launched_from_cli ( )
# ifdef HAVE_MENU
| | menu_driver_is_alive ( )
# endif
)
2016-07-19 04:33:56 +00:00
{
2016-09-11 17:53:34 +00:00
/* Attempt initializing dummy core */
2016-07-19 04:33:56 +00:00
current_core_type = CORE_TYPE_DUMMY ;
if ( ! command_event ( CMD_EVENT_CORE_INIT , & current_core_type ) )
2016-07-19 04:27:46 +00:00
goto error ;
2016-07-19 04:33:56 +00:00
}
else
{
2016-07-19 04:27:46 +00:00
/* Fall back to regular error handling */
goto error ;
}
2016-07-19 04:20:19 +00:00
}
2010-10-01 19:39:15 +00:00
2018-07-25 23:19:14 +00:00
command_event ( CMD_EVENT_CHEATS_INIT , NULL ) ;
2017-01-16 21:04:57 +00:00
drivers_init ( DRIVERS_CMD_ALL ) ;
2016-05-09 18:51:53 +00:00
command_event ( CMD_EVENT_COMMAND_INIT , NULL ) ;
command_event ( CMD_EVENT_REMOTE_INIT , NULL ) ;
2017-11-24 21:18:08 +00:00
command_event ( CMD_EVENT_MAPPER_INIT , NULL ) ;
2016-05-09 18:51:53 +00:00
command_event ( CMD_EVENT_REWIND_INIT , NULL ) ;
command_event ( CMD_EVENT_CONTROLLERS_INIT , NULL ) ;
2018-09-15 22:44:46 +00:00
if ( ! string_is_empty ( global - > record . path ) )
command_event ( CMD_EVENT_RECORD_INIT , NULL ) ;
2016-09-19 01:03:31 +00:00
path_init_savefile ( ) ;
2016-05-09 18:51:53 +00:00
command_event ( CMD_EVENT_SET_PER_GAME_RESOLUTION , NULL ) ;
2014-10-13 05:35:18 +00:00
2017-05-08 01:59:02 +00:00
rarch_error_on_init = false ;
rarch_is_inited = true ;
2016-05-11 18:50:34 +00:00
2018-05-29 04:43:30 +00:00
# ifdef HAVE_DISCORD
2018-05-29 10:41:13 +00:00
if ( command_event ( CMD_EVENT_DISCORD_INIT , NULL ) )
discord_is_inited = true ;
2018-05-29 09:06:43 +00:00
if ( discord_is_inited )
2018-05-29 10:41:13 +00:00
{
discord_userdata_t userdata ;
userdata . status = DISCORD_PRESENCE_MENU ;
command_event ( CMD_EVENT_DISCORD_UPDATE , & userdata ) ;
}
2018-05-29 04:43:30 +00:00
# endif
2019-01-27 16:22:16 +00:00
# ifdef HAVE_MENU
{
settings_t * settings = config_get_ptr ( ) ;
if ( settings - > bools . audio_enable_menu )
audio_driver_load_menu_sounds ( ) ;
}
# endif
2016-05-11 18:50:34 +00:00
return true ;
2011-08-13 02:09:08 +00:00
2012-01-14 13:08:43 +00:00
error :
2016-05-09 18:51:53 +00:00
command_event ( CMD_EVENT_CORE_DEINIT , NULL ) ;
2017-05-08 01:59:02 +00:00
rarch_is_inited = false ;
2018-04-30 18:33:05 +00:00
2016-05-11 18:50:34 +00:00
return false ;
2012-01-14 13:08:43 +00:00
}
2017-05-12 01:39:37 +00:00
bool retroarch_is_on_main_thread ( void )
2014-09-03 16:16:49 +00:00
{
2016-10-18 00:21:51 +00:00
# ifdef HAVE_THREAD_STORAGE
2017-05-12 01:39:37 +00:00
if ( sthread_tls_get ( & rarch_tls ) ! = MAGIC_POINTER )
return false ;
2016-10-17 23:50:19 +00:00
# endif
2017-05-12 01:39:37 +00:00
return true ;
}
2015-03-18 05:47:22 +00:00
2017-05-15 02:31:40 +00:00
void rarch_menu_running ( void )
{
2019-01-27 16:22:16 +00:00
settings_t * settings = config_get_ptr ( ) ;
( void ) settings ;
2017-05-15 02:31:40 +00:00
# ifdef HAVE_MENU
menu_driver_ctl ( RARCH_MENU_CTL_SET_TOGGLE , NULL ) ;
2019-01-27 16:22:16 +00:00
2017-05-17 03:06:52 +00:00
/* Prevent stray input */
input_driver_set_flushing_input ( ) ;
2019-01-27 16:22:16 +00:00
if ( settings & & settings - > bools . audio_enable_menu & & settings - > bools . audio_enable_menu_bgm )
audio_driver_mixer_play_menu_sound_looped ( AUDIO_MIXER_SYSTEM_SLOT_BGM ) ;
2017-05-15 02:31:40 +00:00
# endif
# ifdef HAVE_OVERLAY
2019-01-27 16:22:16 +00:00
if ( settings & & settings - > bools . input_overlay_hide_in_menu )
command_event ( CMD_EVENT_OVERLAY_DEINIT , NULL ) ;
2017-05-15 02:31:40 +00:00
# endif
}
void rarch_menu_running_finished ( void )
{
2019-01-27 16:22:16 +00:00
settings_t * settings = config_get_ptr ( ) ;
( void ) settings ;
2017-05-15 02:31:40 +00:00
# ifdef HAVE_MENU
menu_driver_ctl ( RARCH_MENU_CTL_UNSET_TOGGLE , NULL ) ;
2019-01-27 16:22:16 +00:00
2017-05-17 03:06:52 +00:00
/* Prevent stray input */
input_driver_set_flushing_input ( ) ;
2019-01-27 16:22:16 +00:00
2019-02-28 20:54:46 +00:00
/* Stop menu background music before we exit the menu */
2019-01-27 16:22:16 +00:00
if ( settings & & settings - > bools . audio_enable_menu & & settings - > bools . audio_enable_menu_bgm )
audio_driver_mixer_stop_stream ( AUDIO_MIXER_SYSTEM_SLOT_BGM ) ;
2017-05-15 02:31:40 +00:00
# endif
video_driver_set_texture_enable ( false , false ) ;
# ifdef HAVE_OVERLAY
2019-01-27 16:22:16 +00:00
if ( settings & & settings - > bools . input_overlay_hide_in_menu )
command_event ( CMD_EVENT_OVERLAY_INIT , NULL ) ;
2017-05-15 02:31:40 +00:00
# endif
}
2017-05-15 03:06:23 +00:00
/**
* rarch_game_specific_options :
*
* Returns : true ( 1 ) if a game specific core
* options path has been found ,
* otherwise false ( 0 ) .
* */
static bool rarch_game_specific_options ( char * * output )
{
2017-09-09 04:31:51 +00:00
size_t game_path_size = 8192 * sizeof ( char ) ;
2018-10-29 06:38:26 +00:00
char * game_path = ( char * ) malloc ( game_path_size ) ;
2017-05-15 03:06:23 +00:00
game_path [ 0 ] = ' \0 ' ;
if ( ! retroarch_validate_game_options ( game_path ,
2017-09-09 04:31:51 +00:00
game_path_size , false ) )
2017-11-18 15:48:53 +00:00
goto error ;
2017-05-15 03:06:23 +00:00
if ( ! config_file_exists ( game_path ) )
2017-11-18 15:48:53 +00:00
goto error ;
2017-05-15 03:06:23 +00:00
RARCH_LOG ( " %s %s \n " ,
msg_hash_to_str ( MSG_GAME_SPECIFIC_CORE_OPTIONS_FOUND_AT ) ,
game_path ) ;
* output = strdup ( game_path ) ;
2017-09-09 04:31:51 +00:00
free ( game_path ) ;
2017-05-15 03:06:23 +00:00
return true ;
2017-09-09 04:31:51 +00:00
error :
free ( game_path ) ;
return false ;
2017-05-15 03:06:23 +00:00
}
2017-05-12 01:39:37 +00:00
bool rarch_ctl ( enum rarch_ctl_state state , void * data )
{
2019-01-14 04:25:04 +00:00
static bool has_set_username = false ;
2019-01-12 16:58:35 +00:00
static bool rarch_block_config_read = false ;
static bool rarch_patch_blocked = false ;
static bool runloop_missing_bios = false ; /* TODO/FIXME - not used right now? */
2015-09-26 23:58:24 +00:00
switch ( state )
2014-09-03 16:16:49 +00:00
{
2016-09-29 03:36:21 +00:00
case RARCH_CTL_IS_PATCH_BLOCKED :
return rarch_patch_blocked ;
case RARCH_CTL_SET_PATCH_BLOCKED :
rarch_patch_blocked = true ;
break ;
case RARCH_CTL_UNSET_PATCH_BLOCKED :
rarch_patch_blocked = false ;
break ;
case RARCH_CTL_IS_BPS_PREF :
return rarch_bps_pref ;
case RARCH_CTL_UNSET_BPS_PREF :
rarch_bps_pref = false ;
break ;
case RARCH_CTL_IS_UPS_PREF :
return rarch_ups_pref ;
case RARCH_CTL_UNSET_UPS_PREF :
rarch_ups_pref = false ;
break ;
case RARCH_CTL_IS_IPS_PREF :
return rarch_ips_pref ;
case RARCH_CTL_UNSET_IPS_PREF :
rarch_ips_pref = false ;
break ;
2016-01-19 22:44:32 +00:00
case RARCH_CTL_IS_DUMMY_CORE :
2016-01-20 02:15:50 +00:00
return ( current_core_type = = CORE_TYPE_DUMMY ) ;
2016-04-05 22:30:21 +00:00
case RARCH_CTL_USERNAME_SET :
has_set_username = true ;
break ;
case RARCH_CTL_USERNAME_UNSET :
has_set_username = false ;
break ;
case RARCH_CTL_HAS_SET_USERNAME :
return has_set_username ;
2016-01-19 22:26:47 +00:00
case RARCH_CTL_IS_INITED :
return rarch_is_inited ;
2015-12-07 14:03:54 +00:00
case RARCH_CTL_DESTROY :
2016-04-10 14:40:36 +00:00
has_set_username = false ;
rarch_is_inited = false ;
rarch_error_on_init = false ;
2019-01-12 16:58:35 +00:00
rarch_ctl ( RARCH_CTL_UNSET_BLOCK_CONFIG_READ , NULL ) ;
2016-04-10 14:40:36 +00:00
2017-05-11 07:20:35 +00:00
retroarch_msg_queue_deinit ( ) ;
2017-05-28 13:03:03 +00:00
driver_uninit ( DRIVERS_CMD_ALL ) ;
2016-05-09 18:51:53 +00:00
command_event ( CMD_EVENT_LOG_FILE_DEINIT , NULL ) ;
2016-04-10 14:40:36 +00:00
2017-05-15 03:06:23 +00:00
rarch_ctl ( RARCH_CTL_STATE_FREE , NULL ) ;
2017-05-11 07:20:35 +00:00
global_free ( ) ;
2017-05-15 03:06:23 +00:00
rarch_ctl ( RARCH_CTL_DATA_DEINIT , NULL ) ;
2016-04-10 14:40:36 +00:00
config_free ( ) ;
2016-01-30 04:03:15 +00:00
break ;
2015-12-07 14:01:53 +00:00
case RARCH_CTL_PREINIT :
2017-05-29 23:44:49 +00:00
libretro_free_system_info ( & runloop_system . info ) ;
2016-05-09 18:51:53 +00:00
command_event ( CMD_EVENT_HISTORY_DEINIT , NULL ) ;
2016-05-27 03:05:27 +00:00
config_init ( ) ;
2015-12-07 14:01:53 +00:00
2017-05-11 07:20:35 +00:00
driver_ctl ( RARCH_DRIVER_CTL_DEINIT , NULL ) ;
2017-05-15 03:06:23 +00:00
rarch_ctl ( RARCH_CTL_STATE_FREE , NULL ) ;
2017-05-11 07:20:35 +00:00
global_free ( ) ;
2016-01-30 04:03:15 +00:00
break ;
case RARCH_CTL_MAIN_DEINIT :
2019-02-27 15:47:39 +00:00
if ( ! rarch_is_inited )
2016-01-30 04:03:15 +00:00
return false ;
2016-05-09 18:51:53 +00:00
command_event ( CMD_EVENT_NETPLAY_DEINIT , NULL ) ;
command_event ( CMD_EVENT_COMMAND_DEINIT , NULL ) ;
command_event ( CMD_EVENT_REMOTE_DEINIT , NULL ) ;
2017-09-08 03:30:42 +00:00
command_event ( CMD_EVENT_MAPPER_DEINIT , NULL ) ;
2016-04-10 13:52:06 +00:00
2016-05-09 18:51:53 +00:00
command_event ( CMD_EVENT_AUTOSAVE_DEINIT , NULL ) ;
2016-04-10 13:52:06 +00:00
2016-05-09 18:51:53 +00:00
command_event ( CMD_EVENT_RECORD_DEINIT , NULL ) ;
2016-09-19 02:09:27 +00:00
event_save_files ( ) ;
2016-04-10 13:52:06 +00:00
2016-05-09 18:51:53 +00:00
command_event ( CMD_EVENT_REWIND_DEINIT , NULL ) ;
command_event ( CMD_EVENT_CHEATS_DEINIT , NULL ) ;
command_event ( CMD_EVENT_BSV_MOVIE_DEINIT , NULL ) ;
2016-04-10 13:52:06 +00:00
2016-05-09 18:51:53 +00:00
command_event ( CMD_EVENT_CORE_DEINIT , NULL ) ;
2016-04-10 13:52:06 +00:00
2017-05-27 01:43:53 +00:00
content_deinit ( ) ;
2016-09-19 01:03:31 +00:00
2016-09-25 13:49:09 +00:00
path_deinit_subsystem ( ) ;
2016-09-19 01:03:31 +00:00
path_deinit_savefile ( ) ;
2016-04-10 13:52:06 +00:00
2017-05-08 01:59:02 +00:00
rarch_is_inited = false ;
2016-10-17 23:50:19 +00:00
2016-10-18 00:21:51 +00:00
# ifdef HAVE_THREAD_STORAGE
2016-10-17 23:50:19 +00:00
sthread_tls_delete ( & rarch_tls ) ;
# endif
2016-01-30 04:03:15 +00:00
break ;
2015-12-07 13:59:09 +00:00
case RARCH_CTL_INIT :
2019-02-27 15:47:39 +00:00
if ( rarch_is_inited )
2017-05-28 13:03:03 +00:00
driver_uninit ( DRIVERS_CMD_ALL ) ;
2017-05-12 01:39:37 +00:00
2016-10-18 00:21:51 +00:00
# ifdef HAVE_THREAD_STORAGE
2016-10-17 23:50:19 +00:00
sthread_tls_create ( & rarch_tls ) ;
sthread_tls_set ( & rarch_tls , MAGIC_POINTER ) ;
# endif
2019-02-27 15:47:39 +00:00
drivers_set_active ( ) ;
2015-12-07 13:59:09 +00:00
{
2017-09-09 04:31:51 +00:00
uint8_t i ;
2015-12-07 13:59:09 +00:00
for ( i = 0 ; i < MAX_USERS ; i + + )
2017-01-17 18:59:33 +00:00
input_config_set_device ( i , RETRO_DEVICE_JOYPAD ) ;
2015-12-07 13:59:09 +00:00
}
2017-05-15 03:06:23 +00:00
rarch_ctl ( RARCH_CTL_HTTPSERVER_INIT , NULL ) ;
2017-05-11 07:20:35 +00:00
retroarch_msg_queue_init ( ) ;
2016-01-30 04:03:15 +00:00
break ;
2016-09-28 05:23:14 +00:00
case RARCH_CTL_IS_SRAM_LOAD_DISABLED :
return rarch_is_sram_load_disabled ;
case RARCH_CTL_IS_SRAM_SAVE_DISABLED :
return rarch_is_sram_save_disabled ;
2016-09-28 05:17:14 +00:00
case RARCH_CTL_IS_SRAM_USED :
return rarch_use_sram ;
2016-01-27 18:53:07 +00:00
case RARCH_CTL_SET_SRAM_ENABLE :
2017-01-25 14:44:21 +00:00
{
bool contentless = false ;
2017-01-25 14:51:57 +00:00
bool is_inited = false ;
content_get_status ( & contentless , & is_inited ) ;
2017-05-12 01:39:37 +00:00
rarch_use_sram = ( current_core_type = = CORE_TYPE_PLAIN )
2017-01-25 14:44:21 +00:00
& & ! contentless ;
}
2016-09-28 05:17:14 +00:00
break ;
case RARCH_CTL_SET_SRAM_ENABLE_FORCE :
rarch_use_sram = true ;
break ;
case RARCH_CTL_UNSET_SRAM_ENABLE :
rarch_use_sram = false ;
2016-01-27 18:53:07 +00:00
break ;
2015-11-30 21:09:28 +00:00
case RARCH_CTL_SET_BLOCK_CONFIG_READ :
rarch_block_config_read = true ;
break ;
case RARCH_CTL_UNSET_BLOCK_CONFIG_READ :
rarch_block_config_read = false ;
break ;
case RARCH_CTL_IS_BLOCK_CONFIG_READ :
return rarch_block_config_read ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_SYSTEM_INFO_INIT :
2017-05-29 23:44:49 +00:00
core_get_system_info ( & runloop_system . info ) ;
2015-09-27 00:04:53 +00:00
2017-05-29 23:44:49 +00:00
if ( ! runloop_system . info . library_name )
runloop_system . info . library_name = msg_hash_to_str ( MSG_UNKNOWN ) ;
if ( ! runloop_system . info . library_version )
runloop_system . info . library_version = " v0 " ;
2014-09-03 16:16:49 +00:00
2017-05-29 23:44:49 +00:00
video_driver_set_title_buf ( ) ;
2016-08-01 18:47:19 +00:00
2017-05-29 23:44:49 +00:00
strlcpy ( runloop_system . valid_extensions ,
runloop_system . info . valid_extensions ?
runloop_system . info . valid_extensions : DEFAULT_EXT ,
sizeof ( runloop_system . valid_extensions ) ) ;
2017-05-15 03:06:23 +00:00
break ;
case RARCH_CTL_GET_CORE_OPTION_SIZE :
2016-10-01 04:06:07 +00:00
{
2017-05-15 03:06:23 +00:00
unsigned * idx = ( unsigned * ) data ;
if ( ! idx )
return false ;
* idx = ( unsigned ) core_option_manager_size ( runloop_core_options ) ;
2016-10-01 04:06:07 +00:00
}
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_HAS_CORE_OPTIONS :
2017-10-02 22:53:09 +00:00
return ( runloop_core_options ! = NULL ) ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_CORE_OPTIONS_LIST_GET :
2016-10-01 04:02:18 +00:00
{
2017-05-15 03:06:23 +00:00
core_option_manager_t * * coreopts = ( core_option_manager_t * * ) data ;
if ( ! coreopts )
return false ;
* coreopts = runloop_core_options ;
2016-10-01 04:02:18 +00:00
}
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_SYSTEM_INFO_FREE :
if ( runloop_system . subsystem . data )
free ( runloop_system . subsystem . data ) ;
runloop_system . subsystem . data = NULL ;
runloop_system . subsystem . size = 0 ;
if ( runloop_system . ports . data )
free ( runloop_system . ports . data ) ;
runloop_system . ports . data = NULL ;
runloop_system . ports . size = 0 ;
if ( runloop_system . mmaps . descriptors )
free ( ( void * ) runloop_system . mmaps . descriptors ) ;
runloop_system . mmaps . descriptors = NULL ;
runloop_system . mmaps . num_descriptors = 0 ;
2019-01-10 01:49:25 +00:00
rarch_ctl ( RARCH_CTL_UNSET_KEY_EVENT , NULL ) ;
2017-05-15 03:06:23 +00:00
runloop_frontend_key_event = NULL ;
audio_driver_unset_callback ( ) ;
2017-05-28 15:21:57 +00:00
2017-05-29 23:44:49 +00:00
runloop_system . info . library_name = NULL ;
runloop_system . info . library_version = NULL ;
runloop_system . info . valid_extensions = NULL ;
runloop_system . info . need_fullpath = false ;
runloop_system . info . block_extract = false ;
2017-05-28 15:21:57 +00:00
2017-05-15 03:06:23 +00:00
memset ( & runloop_system , 0 , sizeof ( rarch_system_info_t ) ) ;
2016-08-01 18:54:16 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_SET_FRAME_TIME_LAST :
runloop_frame_time_last = 0 ;
2016-08-01 18:47:19 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_SET_OVERRIDES_ACTIVE :
runloop_overrides_active = true ;
2016-08-01 19:51:23 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_UNSET_OVERRIDES_ACTIVE :
runloop_overrides_active = false ;
2016-08-01 19:51:23 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_IS_OVERRIDES_ACTIVE :
return runloop_overrides_active ;
2017-08-05 05:37:26 +00:00
case RARCH_CTL_SET_REMAPS_CORE_ACTIVE :
runloop_remaps_core_active = true ;
break ;
case RARCH_CTL_UNSET_REMAPS_CORE_ACTIVE :
runloop_remaps_core_active = false ;
break ;
case RARCH_CTL_IS_REMAPS_CORE_ACTIVE :
return runloop_remaps_core_active ;
case RARCH_CTL_SET_REMAPS_GAME_ACTIVE :
runloop_remaps_game_active = true ;
break ;
case RARCH_CTL_UNSET_REMAPS_GAME_ACTIVE :
runloop_remaps_game_active = false ;
break ;
case RARCH_CTL_IS_REMAPS_GAME_ACTIVE :
return runloop_remaps_game_active ;
2018-05-14 04:17:44 +00:00
case RARCH_CTL_SET_REMAPS_CONTENT_DIR_ACTIVE :
runloop_remaps_content_dir_active = true ;
break ;
case RARCH_CTL_UNSET_REMAPS_CONTENT_DIR_ACTIVE :
runloop_remaps_content_dir_active = false ;
break ;
case RARCH_CTL_IS_REMAPS_CONTENT_DIR_ACTIVE :
return runloop_remaps_content_dir_active ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_SET_MISSING_BIOS :
runloop_missing_bios = true ;
2016-08-01 19:51:23 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_UNSET_MISSING_BIOS :
runloop_missing_bios = false ;
2016-08-01 19:51:23 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_IS_MISSING_BIOS :
return runloop_missing_bios ;
case RARCH_CTL_IS_GAME_OPTIONS_ACTIVE :
return runloop_game_options_active ;
case RARCH_CTL_SET_FRAME_LIMIT :
{
settings_t * settings = config_get_ptr ( ) ;
struct retro_system_av_info * av_info =
video_viewport_get_system_av_info ( ) ;
float fastforward_ratio =
( settings - > floats . fastforward_ratio = = 0.0f )
? 1.0f : settings - > floats . fastforward_ratio ;
frame_limit_last_time = cpu_features_get_time_usec ( ) ;
frame_limit_minimum_time = ( retro_time_t ) roundf ( 1000000.0f
/ ( av_info - > timing . fps * fastforward_ratio ) ) ;
}
2016-08-01 19:51:23 +00:00
break ;
2019-02-12 05:32:01 +00:00
case RARCH_CTL_CONTENT_RUNTIME_LOG_INIT :
2019-03-06 12:24:35 +00:00
{
const char * content_path = path_get ( RARCH_PATH_CONTENT ) ;
const char * core_path = path_get ( RARCH_PATH_CORE ) ;
2019-03-04 15:30:12 +00:00
libretro_core_runtime_last = cpu_features_get_time_usec ( ) ;
2019-02-12 05:32:01 +00:00
libretro_core_runtime_usec = 0 ;
2019-03-06 12:24:35 +00:00
/* Have to cache content and core path here, otherwise
* logging fails if new content is loaded without
* closing existing content
* i . e . RARCH_PATH_CONTENT and RARCH_PATH_CORE get
* updated when the new content is loaded , which
* happens * before * RARCH_CTL_CONTENT_RUNTIME_LOG_DEINIT
* - > using RARCH_PATH_CONTENT and RARCH_PATH_CORE
* directly in RARCH_CTL_CONTENT_RUNTIME_LOG_DEINIT
* can therefore lead to the runtime of the currently
* loaded content getting written to the * new *
* content ' s log file . . . */
memset ( runtime_content_path , 0 , sizeof ( runtime_content_path ) ) ;
memset ( runtime_core_path , 0 , sizeof ( runtime_core_path ) ) ;
if ( ! string_is_empty ( content_path ) )
strlcpy ( runtime_content_path , content_path , sizeof ( runtime_content_path ) ) ;
if ( ! string_is_empty ( core_path ) )
strlcpy ( runtime_core_path , core_path , sizeof ( runtime_core_path ) ) ;
2019-02-12 05:32:01 +00:00
break ;
2019-03-06 12:24:35 +00:00
}
2019-02-12 05:32:01 +00:00
case RARCH_CTL_CONTENT_RUNTIME_LOG_DEINIT :
{
settings_t * settings = config_get_ptr ( ) ;
2019-02-27 16:19:29 +00:00
unsigned hours = 0 ;
unsigned minutes = 0 ;
unsigned seconds = 0 ;
2019-02-12 05:32:01 +00:00
char log [ PATH_MAX_LENGTH ] = { 0 } ;
2019-02-27 16:19:29 +00:00
int n = 0 ;
2019-02-12 05:32:01 +00:00
2019-02-27 16:19:29 +00:00
runtime_log_convert_usec2hms ( libretro_core_runtime_usec , & hours , & minutes , & seconds ) ;
2019-02-12 05:32:01 +00:00
2019-02-27 16:19:29 +00:00
n = snprintf ( log , sizeof ( log ) ,
2019-03-02 22:36:53 +00:00
" Content ran for a total of: %02u hours, %02u minutes, %02u seconds. " ,
2019-02-27 16:19:29 +00:00
hours , minutes , seconds ) ;
if ( ( n < 0 ) | | ( n > = PATH_MAX_LENGTH ) )
n = 0 ; /* Just silence any potential gcc warnings... */
2019-03-02 22:36:53 +00:00
RARCH_LOG ( " %s \n " , log ) ;
2019-02-12 05:32:01 +00:00
2019-03-07 12:28:21 +00:00
/* Only write to file if content has run for a non-zero length of time */
if ( libretro_core_runtime_usec > 0 )
2019-02-12 05:32:01 +00:00
{
2019-03-07 12:28:21 +00:00
/* Per core logging */
if ( settings - > bools . content_runtime_log )
update_runtime_log ( true ) ;
2019-02-12 05:32:01 +00:00
2019-03-07 12:28:21 +00:00
/* Aggregate logging */
if ( settings - > bools . content_runtime_log_aggregate )
update_runtime_log ( false ) ;
2019-02-12 05:32:01 +00:00
}
2019-03-06 12:24:35 +00:00
/* Reset runtime + content/core paths, to prevent any
* possibility of duplicate logging */
2019-03-04 11:33:19 +00:00
libretro_core_runtime_usec = 0 ;
2019-03-06 12:24:35 +00:00
memset ( runtime_content_path , 0 , sizeof ( runtime_content_path ) ) ;
memset ( runtime_core_path , 0 , sizeof ( runtime_core_path ) ) ;
2019-03-04 11:33:19 +00:00
2019-02-12 05:32:01 +00:00
break ;
}
2017-05-15 03:06:23 +00:00
case RARCH_CTL_GET_PERFCNT :
{
bool * * perfcnt = ( bool * * ) data ;
if ( ! perfcnt )
return false ;
* perfcnt = & runloop_perfcnt_enable ;
}
2016-08-01 19:51:23 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_SET_PERFCNT_ENABLE :
runloop_perfcnt_enable = true ;
2016-08-01 19:51:23 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_UNSET_PERFCNT_ENABLE :
runloop_perfcnt_enable = false ;
2016-09-15 03:54:18 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_IS_PERFCNT_ENABLE :
return runloop_perfcnt_enable ;
case RARCH_CTL_SET_NONBLOCK_FORCED :
runloop_force_nonblock = true ;
2016-08-01 19:51:23 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_UNSET_NONBLOCK_FORCED :
runloop_force_nonblock = false ;
2016-08-01 19:51:23 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_IS_NONBLOCK_FORCED :
return runloop_force_nonblock ;
case RARCH_CTL_SET_FRAME_TIME :
{
const struct retro_frame_time_callback * info =
( const struct retro_frame_time_callback * ) data ;
# ifdef HAVE_NETWORKING
/* retro_run() will be called in very strange and
* mysterious ways , have to disable it . */
if ( netplay_driver_ctl ( RARCH_NETPLAY_CTL_IS_ENABLED , NULL ) )
return false ;
# endif
runloop_frame_time = * info ;
}
2016-08-01 19:51:23 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_GET_WINDOWED_SCALE :
{
unsigned * * scale = ( unsigned * * ) data ;
if ( ! scale )
return false ;
* scale = ( unsigned * ) & runloop_pending_windowed_scale ;
}
2016-08-01 18:41:42 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_SET_WINDOWED_SCALE :
2016-10-01 04:14:30 +00:00
{
2017-05-15 03:06:23 +00:00
unsigned * idx = ( unsigned * ) data ;
if ( ! idx )
return false ;
runloop_pending_windowed_scale = * idx ;
2016-10-01 04:14:30 +00:00
}
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_SET_LIBRETRO_PATH :
return path_set ( RARCH_PATH_CORE , ( const char * ) data ) ;
case RARCH_CTL_FRAME_TIME_FREE :
memset ( & runloop_frame_time , 0 ,
sizeof ( struct retro_frame_time_callback ) ) ;
runloop_frame_time_last = 0 ;
runloop_max_frames = 0 ;
2016-08-01 18:54:16 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_STATE_FREE :
runloop_perfcnt_enable = false ;
runloop_idle = false ;
runloop_paused = false ;
runloop_slowmotion = false ;
runloop_overrides_active = false ;
runloop_autosave = false ;
rarch_ctl ( RARCH_CTL_FRAME_TIME_FREE , NULL ) ;
2016-08-01 18:47:19 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_IS_IDLE :
return runloop_idle ;
case RARCH_CTL_SET_IDLE :
{
bool * ptr = ( bool * ) data ;
if ( ! ptr )
return false ;
runloop_idle = * ptr ;
}
2016-08-01 19:51:23 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_SET_PAUSED :
{
bool * ptr = ( bool * ) data ;
if ( ! ptr )
return false ;
runloop_paused = * ptr ;
}
break ;
case RARCH_CTL_IS_PAUSED :
return runloop_paused ;
case RARCH_CTL_TASK_INIT :
{
# ifdef HAVE_THREADS
settings_t * settings = config_get_ptr ( ) ;
bool threaded_enable = settings - > bools . threaded_data_runloop_enable ;
# else
bool threaded_enable = false ;
# endif
task_queue_deinit ( ) ;
2018-11-22 14:45:52 +00:00
task_queue_init ( threaded_enable , runloop_task_msg_queue_push ) ;
2017-05-15 03:06:23 +00:00
}
break ;
case RARCH_CTL_SET_CORE_SHUTDOWN :
runloop_core_shutdown_initiated = true ;
break ;
case RARCH_CTL_SET_SHUTDOWN :
runloop_shutdown_initiated = true ;
break ;
2019-01-10 01:35:03 +00:00
case RARCH_CTL_UNSET_SHUTDOWN :
runloop_shutdown_initiated = false ;
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_IS_SHUTDOWN :
return runloop_shutdown_initiated ;
case RARCH_CTL_DATA_DEINIT :
task_queue_deinit ( ) ;
break ;
case RARCH_CTL_IS_CORE_OPTION_UPDATED :
if ( ! runloop_core_options )
return false ;
return core_option_manager_updated ( runloop_core_options ) ;
case RARCH_CTL_CORE_OPTION_PREV :
{
unsigned * idx = ( unsigned * ) data ;
if ( ! idx )
return false ;
core_option_manager_prev ( runloop_core_options , * idx ) ;
}
break ;
case RARCH_CTL_CORE_OPTION_NEXT :
{
unsigned * idx = ( unsigned * ) data ;
if ( ! idx )
return false ;
core_option_manager_next ( runloop_core_options , * idx ) ;
}
break ;
case RARCH_CTL_CORE_OPTIONS_GET :
{
struct retro_variable * var = ( struct retro_variable * ) data ;
if ( ! runloop_core_options | | ! var )
return false ;
RARCH_LOG ( " Environ GET_VARIABLE %s: \n " , var - > key ) ;
core_option_manager_get ( runloop_core_options , var ) ;
RARCH_LOG ( " \t %s \n " , var - > value ? var - > value :
msg_hash_to_str ( MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE ) ) ;
}
break ;
case RARCH_CTL_CORE_OPTIONS_INIT :
{
settings_t * settings = config_get_ptr ( ) ;
char * game_options_path = NULL ;
bool ret = false ;
const struct retro_variable * vars =
( const struct retro_variable * ) data ;
if ( settings & & settings - > bools . game_specific_options )
ret = rarch_game_specific_options ( & game_options_path ) ;
2018-09-26 12:03:29 +00:00
if ( ret )
2017-05-15 03:06:23 +00:00
{
runloop_game_options_active = true ;
runloop_core_options =
core_option_manager_new ( game_options_path , vars ) ;
free ( game_options_path ) ;
}
else
{
char buf [ PATH_MAX_LENGTH ] ;
const char * options_path = NULL ;
buf [ 0 ] = ' \0 ' ;
if ( settings )
options_path = settings - > paths . path_core_options ;
if ( string_is_empty ( options_path ) & & ! path_is_empty ( RARCH_PATH_CONFIG ) )
{
fill_pathname_resolve_relative ( buf , path_get ( RARCH_PATH_CONFIG ) ,
file_path_str ( FILE_PATH_CORE_OPTIONS_CONFIG ) , sizeof ( buf ) ) ;
options_path = buf ;
}
runloop_game_options_active = false ;
if ( ! string_is_empty ( options_path ) )
runloop_core_options =
core_option_manager_new ( options_path , vars ) ;
}
}
break ;
case RARCH_CTL_CORE_OPTIONS_DEINIT :
{
if ( ! runloop_core_options )
return false ;
/* check if game options file was just created and flush
to that file instead */
2018-09-26 12:03:29 +00:00
if ( ! path_is_empty ( RARCH_PATH_CORE_OPTIONS ) )
2017-05-15 03:06:23 +00:00
{
core_option_manager_flush_game_specific ( runloop_core_options ,
path_get ( RARCH_PATH_CORE_OPTIONS ) ) ;
path_clear ( RARCH_PATH_CORE_OPTIONS ) ;
}
else
core_option_manager_flush ( runloop_core_options ) ;
if ( runloop_game_options_active )
runloop_game_options_active = false ;
if ( runloop_core_options )
core_option_manager_free ( runloop_core_options ) ;
runloop_core_options = NULL ;
}
break ;
case RARCH_CTL_KEY_EVENT_GET :
{
retro_keyboard_event_t * * key_event =
( retro_keyboard_event_t * * ) data ;
if ( ! key_event )
return false ;
* key_event = & runloop_key_event ;
}
break ;
2019-01-10 01:49:25 +00:00
case RARCH_CTL_UNSET_KEY_EVENT :
runloop_key_event = NULL ;
break ;
2017-05-15 03:06:23 +00:00
case RARCH_CTL_FRONTEND_KEY_EVENT_GET :
{
retro_keyboard_event_t * * key_event =
( retro_keyboard_event_t * * ) data ;
if ( ! key_event )
return false ;
* key_event = & runloop_frontend_key_event ;
}
break ;
case RARCH_CTL_HTTPSERVER_INIT :
# if defined(HAVE_HTTPSERVER) && defined(HAVE_ZLIB)
httpserver_init ( 8888 ) ;
# endif
break ;
case RARCH_CTL_HTTPSERVER_DESTROY :
# if defined(HAVE_HTTPSERVER) && defined(HAVE_ZLIB)
httpserver_destroy ( ) ;
# endif
break ;
case RARCH_CTL_NONE :
default :
return false ;
}
return true ;
}
bool retroarch_is_forced_fullscreen ( void )
{
return rarch_force_fullscreen ;
}
2017-12-17 17:56:26 +00:00
void retroarch_unset_forced_fullscreen ( void )
{
rarch_force_fullscreen = false ;
}
2018-12-12 00:34:12 +00:00
bool retroarch_is_switching_display_mode ( void )
{
return rarch_is_switching_display_mode ;
}
void retroarch_set_switching_display_mode ( void )
{
rarch_is_switching_display_mode = true ;
}
void retroarch_unset_switching_display_mode ( void )
{
rarch_is_switching_display_mode = false ;
}
2018-01-30 03:11:08 +00:00
/* set a runtime shader preset without overwriting the settings value */
2018-01-31 03:11:09 +00:00
void retroarch_set_shader_preset ( const char * preset )
2018-01-30 03:11:08 +00:00
{
if ( ! string_is_empty ( preset ) )
strlcpy ( runtime_shader_preset , preset , sizeof ( runtime_shader_preset ) ) ;
else
runtime_shader_preset [ 0 ] = ' \0 ' ;
}
/* unset a runtime shader preset */
void retroarch_unset_shader_preset ( void )
{
runtime_shader_preset [ 0 ] = ' \0 ' ;
}
/* get the name of the current shader preset */
char * retroarch_get_shader_preset ( void )
{
settings_t * settings = config_get_ptr ( ) ;
if ( ! settings - > bools . video_shader_enable )
2018-01-31 03:38:03 +00:00
return NULL ;
2018-01-30 03:11:08 +00:00
if ( ! string_is_empty ( runtime_shader_preset ) )
return runtime_shader_preset ;
else if ( ! string_is_empty ( settings - > paths . path_shader ) )
return settings - > paths . path_shader ;
2018-10-11 01:26:39 +00:00
return NULL ;
2018-01-30 03:11:08 +00:00
}
2017-05-15 03:06:23 +00:00
bool retroarch_override_setting_is_set ( enum rarch_override_setting enum_idx , void * data )
{
switch ( enum_idx )
{
case RARCH_OVERRIDE_SETTING_LIBRETRO_DEVICE :
{
unsigned * val = ( unsigned * ) data ;
if ( val )
{
unsigned bit = * val ;
2017-12-05 11:07:35 +00:00
return BIT256_GET ( has_set_libretro_device , bit ) ;
2017-05-15 03:06:23 +00:00
}
}
2016-08-01 19:51:23 +00:00
break ;
2017-05-15 03:06:23 +00:00
case RARCH_OVERRIDE_SETTING_VERBOSITY :
return has_set_verbosity ;
case RARCH_OVERRIDE_SETTING_LIBRETRO :
return has_set_libretro ;
case RARCH_OVERRIDE_SETTING_LIBRETRO_DIRECTORY :
return has_set_libretro_directory ;
case RARCH_OVERRIDE_SETTING_SAVE_PATH :
return has_set_save_path ;
2016-08-01 19:51:23 +00:00
case RARCH_OVERRIDE_SETTING_STATE_PATH :
2017-05-15 03:06:23 +00:00
return has_set_state_path ;
case RARCH_OVERRIDE_SETTING_NETPLAY_MODE :
return has_set_netplay_mode ;
case RARCH_OVERRIDE_SETTING_NETPLAY_IP_ADDRESS :
return has_set_netplay_ip_address ;
case RARCH_OVERRIDE_SETTING_NETPLAY_IP_PORT :
return has_set_netplay_ip_port ;
case RARCH_OVERRIDE_SETTING_NETPLAY_STATELESS_MODE :
return has_set_netplay_stateless_mode ;
case RARCH_OVERRIDE_SETTING_NETPLAY_CHECK_FRAMES :
return has_set_netplay_check_frames ;
case RARCH_OVERRIDE_SETTING_UPS_PREF :
return has_set_ups_pref ;
case RARCH_OVERRIDE_SETTING_BPS_PREF :
return has_set_bps_pref ;
case RARCH_OVERRIDE_SETTING_IPS_PREF :
return has_set_ips_pref ;
case RARCH_OVERRIDE_SETTING_NONE :
default :
break ;
}
return false ;
}
void retroarch_override_setting_set ( enum rarch_override_setting enum_idx , void * data )
{
switch ( enum_idx )
{
case RARCH_OVERRIDE_SETTING_LIBRETRO_DEVICE :
{
unsigned * val = ( unsigned * ) data ;
if ( val )
{
unsigned bit = * val ;
2017-12-05 11:07:35 +00:00
BIT256_SET ( has_set_libretro_device , bit ) ;
2017-05-15 03:06:23 +00:00
}
}
break ;
case RARCH_OVERRIDE_SETTING_VERBOSITY :
has_set_verbosity = true ;
break ;
case RARCH_OVERRIDE_SETTING_LIBRETRO :
has_set_libretro = true ;
break ;
case RARCH_OVERRIDE_SETTING_LIBRETRO_DIRECTORY :
has_set_libretro_directory = true ;
break ;
case RARCH_OVERRIDE_SETTING_SAVE_PATH :
has_set_save_path = true ;
break ;
case RARCH_OVERRIDE_SETTING_STATE_PATH :
has_set_state_path = true ;
2016-08-01 19:51:23 +00:00
break ;
case RARCH_OVERRIDE_SETTING_NETPLAY_MODE :
2017-05-15 03:06:23 +00:00
has_set_netplay_mode = true ;
2016-08-01 19:51:23 +00:00
break ;
case RARCH_OVERRIDE_SETTING_NETPLAY_IP_ADDRESS :
2017-05-15 03:06:23 +00:00
has_set_netplay_ip_address = true ;
2016-08-01 19:51:23 +00:00
break ;
case RARCH_OVERRIDE_SETTING_NETPLAY_IP_PORT :
2017-05-15 03:06:23 +00:00
has_set_netplay_ip_port = true ;
2016-08-01 19:51:23 +00:00
break ;
2016-12-16 04:09:55 +00:00
case RARCH_OVERRIDE_SETTING_NETPLAY_STATELESS_MODE :
2017-05-15 03:06:23 +00:00
has_set_netplay_stateless_mode = true ;
2016-08-01 19:51:23 +00:00
break ;
2016-09-15 03:54:18 +00:00
case RARCH_OVERRIDE_SETTING_NETPLAY_CHECK_FRAMES :
2017-05-15 03:06:23 +00:00
has_set_netplay_check_frames = true ;
2016-09-15 03:54:18 +00:00
break ;
2016-08-01 19:51:23 +00:00
case RARCH_OVERRIDE_SETTING_UPS_PREF :
2017-05-15 03:06:23 +00:00
has_set_ups_pref = true ;
2016-08-01 19:51:23 +00:00
break ;
case RARCH_OVERRIDE_SETTING_BPS_PREF :
2017-05-15 03:06:23 +00:00
has_set_bps_pref = true ;
2016-08-01 19:51:23 +00:00
break ;
case RARCH_OVERRIDE_SETTING_IPS_PREF :
2017-05-15 03:06:23 +00:00
has_set_ips_pref = true ;
2016-08-01 19:51:23 +00:00
break ;
2016-08-01 18:41:42 +00:00
case RARCH_OVERRIDE_SETTING_NONE :
default :
break ;
}
}
2017-05-15 03:06:23 +00:00
void retroarch_override_setting_unset ( enum rarch_override_setting enum_idx , void * data )
{
switch ( enum_idx )
{
case RARCH_OVERRIDE_SETTING_LIBRETRO_DEVICE :
{
unsigned * val = ( unsigned * ) data ;
if ( val )
{
unsigned bit = * val ;
2017-12-05 11:07:35 +00:00
BIT256_CLEAR ( has_set_libretro_device , bit ) ;
2017-05-15 03:06:23 +00:00
}
}
break ;
case RARCH_OVERRIDE_SETTING_VERBOSITY :
has_set_verbosity = false ;
break ;
case RARCH_OVERRIDE_SETTING_LIBRETRO :
has_set_libretro = false ;
break ;
case RARCH_OVERRIDE_SETTING_LIBRETRO_DIRECTORY :
has_set_libretro_directory = false ;
break ;
case RARCH_OVERRIDE_SETTING_SAVE_PATH :
has_set_save_path = false ;
break ;
case RARCH_OVERRIDE_SETTING_STATE_PATH :
has_set_state_path = false ;
break ;
case RARCH_OVERRIDE_SETTING_NETPLAY_MODE :
has_set_netplay_mode = false ;
break ;
case RARCH_OVERRIDE_SETTING_NETPLAY_IP_ADDRESS :
has_set_netplay_ip_address = false ;
break ;
case RARCH_OVERRIDE_SETTING_NETPLAY_IP_PORT :
has_set_netplay_ip_port = false ;
break ;
case RARCH_OVERRIDE_SETTING_NETPLAY_STATELESS_MODE :
has_set_netplay_stateless_mode = false ;
break ;
case RARCH_OVERRIDE_SETTING_NETPLAY_CHECK_FRAMES :
has_set_netplay_check_frames = false ;
break ;
case RARCH_OVERRIDE_SETTING_UPS_PREF :
has_set_ups_pref = false ;
break ;
case RARCH_OVERRIDE_SETTING_BPS_PREF :
has_set_bps_pref = false ;
break ;
case RARCH_OVERRIDE_SETTING_IPS_PREF :
has_set_ips_pref = false ;
break ;
case RARCH_OVERRIDE_SETTING_NONE :
default :
break ;
}
}
2016-05-09 05:09:26 +00:00
int retroarch_get_capabilities ( enum rarch_capabilities type ,
2016-01-26 04:38:40 +00:00
char * s , size_t len )
2015-11-28 19:11:55 +00:00
{
switch ( type )
{
case RARCH_CAPABILITIES_CPU :
{
2016-05-10 07:17:04 +00:00
uint64_t cpu = cpu_features_get ( ) ;
2015-11-28 19:11:55 +00:00
if ( cpu & RETRO_SIMD_MMX )
strlcat ( s , " MMX " , len ) ;
if ( cpu & RETRO_SIMD_MMXEXT )
strlcat ( s , " MMXEXT " , len ) ;
if ( cpu & RETRO_SIMD_SSE )
strlcat ( s , " SSE1 " , len ) ;
if ( cpu & RETRO_SIMD_SSE2 )
strlcat ( s , " SSE2 " , len ) ;
if ( cpu & RETRO_SIMD_SSE3 )
strlcat ( s , " SSE3 " , len ) ;
if ( cpu & RETRO_SIMD_SSSE3 )
strlcat ( s , " SSSE3 " , len ) ;
if ( cpu & RETRO_SIMD_SSE4 )
strlcat ( s , " SSE4 " , len ) ;
if ( cpu & RETRO_SIMD_SSE42 )
strlcat ( s , " SSE4.2 " , len ) ;
if ( cpu & RETRO_SIMD_AVX )
strlcat ( s , " AVX " , len ) ;
if ( cpu & RETRO_SIMD_AVX2 )
strlcat ( s , " AVX2 " , len ) ;
if ( cpu & RETRO_SIMD_VFPU )
strlcat ( s , " VFPU " , len ) ;
if ( cpu & RETRO_SIMD_NEON )
strlcat ( s , " NEON " , len ) ;
2016-05-14 11:37:07 +00:00
if ( cpu & RETRO_SIMD_VFPV3 )
strlcat ( s , " VFPv3 " , len ) ;
if ( cpu & RETRO_SIMD_VFPV4 )
strlcat ( s , " VFPv4 " , len ) ;
2015-11-28 19:11:55 +00:00
if ( cpu & RETRO_SIMD_PS )
strlcat ( s , " PS " , len ) ;
if ( cpu & RETRO_SIMD_AES )
strlcat ( s , " AES " , len ) ;
if ( cpu & RETRO_SIMD_VMX )
strlcat ( s , " VMX " , len ) ;
if ( cpu & RETRO_SIMD_VMX128 )
strlcat ( s , " VMX128 " , len ) ;
2016-10-18 15:39:02 +00:00
if ( cpu & RETRO_SIMD_ASIMD )
strlcat ( s , " ASIMD " , len ) ;
2015-11-28 19:11:55 +00:00
}
break ;
case RARCH_CAPABILITIES_COMPILER :
# if defined(_MSC_VER)
2016-11-08 14:17:02 +00:00
snprintf ( s , len , " %s: MSVC (%d) %u-bit " ,
msg_hash_to_str ( MSG_COMPILER ) ,
_MSC_VER , ( unsigned )
2015-11-28 19:11:55 +00:00
( CHAR_BIT * sizeof ( size_t ) ) ) ;
# elif defined(__SNC__)
2016-11-08 14:17:02 +00:00
snprintf ( s , len , " %s: SNC (%d) %u-bit " ,
msg_hash_to_str ( MSG_COMPILER ) ,
2015-11-28 19:11:55 +00:00
__SN_VER__ , ( unsigned ) ( CHAR_BIT * sizeof ( size_t ) ) ) ;
# elif defined(_WIN32) && defined(__GNUC__)
2016-11-08 14:17:02 +00:00
snprintf ( s , len , " %s: MinGW (%d.%d.%d) %u-bit " ,
msg_hash_to_str ( MSG_COMPILER ) ,
2015-11-28 19:11:55 +00:00
__GNUC__ , __GNUC_MINOR__ , __GNUC_PATCHLEVEL__ , ( unsigned )
( CHAR_BIT * sizeof ( size_t ) ) ) ;
# elif defined(__clang__)
2016-11-08 14:17:02 +00:00
snprintf ( s , len , " %s: Clang/LLVM (%s) %u-bit " ,
msg_hash_to_str ( MSG_COMPILER ) ,
2015-11-28 19:11:55 +00:00
__clang_version__ , ( unsigned ) ( CHAR_BIT * sizeof ( size_t ) ) ) ;
# elif defined(__GNUC__)
2016-11-08 14:17:02 +00:00
snprintf ( s , len , " %s: GCC (%d.%d.%d) %u-bit " ,
msg_hash_to_str ( MSG_COMPILER ) ,
2015-11-28 19:11:55 +00:00
__GNUC__ , __GNUC_MINOR__ , __GNUC_PATCHLEVEL__ , ( unsigned )
( CHAR_BIT * sizeof ( size_t ) ) ) ;
# else
2016-11-08 14:17:02 +00:00
snprintf ( s , len , " %s %u-bit " ,
msg_hash_to_str ( MSG_UNKNOWN_COMPILER ) ,
2015-11-28 19:11:55 +00:00
( unsigned ) ( CHAR_BIT * sizeof ( size_t ) ) ) ;
# endif
break ;
default :
case RARCH_CAPABILITIES_NONE :
break ;
}
return 0 ;
}
2015-11-29 01:27:48 +00:00
2016-05-27 19:16:25 +00:00
void retroarch_set_current_core_type ( enum rarch_core_type type , bool explicitly_set )
2016-05-27 17:26:45 +00:00
{
2016-10-03 14:42:08 +00:00
if ( explicitly_set & & ! has_set_core )
2016-05-27 19:16:25 +00:00
{
2016-10-03 14:42:08 +00:00
has_set_core = true ;
2016-05-27 19:16:25 +00:00
explicit_current_core_type = type ;
2016-06-27 04:13:09 +00:00
current_core_type = type ;
2016-05-27 19:16:25 +00:00
}
2016-10-03 14:42:08 +00:00
else if ( ! has_set_core )
2016-05-27 19:16:25 +00:00
current_core_type = type ;
2016-05-27 17:26:45 +00:00
}
2015-11-29 01:27:48 +00:00
/**
2016-05-09 05:09:26 +00:00
* retroarch_fail :
2015-11-29 01:27:48 +00:00
* @ error_code : Error code .
* @ error : Error message to show .
*
* Sanely kills the program .
* */
2016-05-09 05:09:26 +00:00
void retroarch_fail ( int error_code , const char * error )
2015-11-29 01:27:48 +00:00
{
2016-05-09 05:09:26 +00:00
/* We cannot longjmp unless we're in retroarch_main_init().
2016-03-10 22:36:46 +00:00
* If not , something went very wrong , and we should
2015-11-29 01:27:48 +00:00
* just exit right away . */
2017-05-08 01:59:02 +00:00
retro_assert ( rarch_error_on_init ) ;
2015-11-29 01:27:48 +00:00
2015-11-30 18:30:05 +00:00
strlcpy ( error_string , error , sizeof ( error_string ) ) ;
longjmp ( error_sjlj_context , error_code ) ;
2015-11-29 01:27:48 +00:00
}
2017-05-08 01:54:51 +00:00
bool retroarch_main_quit ( void )
{
2019-02-07 00:01:11 +00:00
# ifdef HAVE_DISCORD
if ( discord_is_inited )
{
discord_userdata_t userdata ;
userdata . status = DISCORD_PRESENCE_SHUTDOWN ;
command_event ( CMD_EVENT_DISCORD_UPDATE , & userdata ) ;
}
command_event ( CMD_EVENT_DISCORD_DEINIT , NULL ) ;
discord_is_inited = false ;
# endif
2019-01-10 01:35:35 +00:00
if ( ! rarch_ctl ( RARCH_CTL_IS_SHUTDOWN , NULL ) )
2017-05-31 05:34:01 +00:00
{
command_event ( CMD_EVENT_AUTOSAVE_STATE , NULL ) ;
command_event ( CMD_EVENT_DISABLE_OVERRIDES , NULL ) ;
command_event ( CMD_EVENT_RESTORE_DEFAULT_SHADER_PRESET , NULL ) ;
2017-08-05 04:56:17 +00:00
command_event ( CMD_EVENT_RESTORE_REMAPS , NULL ) ;
2017-05-31 05:34:01 +00:00
}
2017-05-08 01:54:51 +00:00
2019-01-10 01:35:03 +00:00
rarch_ctl ( RARCH_CTL_SET_SHUTDOWN , NULL ) ;
2017-05-15 02:31:40 +00:00
rarch_menu_running_finished ( ) ;
2017-05-08 01:54:51 +00:00
return true ;
}
2017-05-11 07:11:46 +00:00
global_t * global_get_ptr ( void )
{
static struct global g_extern ;
return & g_extern ;
}
2019-02-21 09:23:21 +00:00
void runloop_task_msg_queue_push ( retro_task_t * task , const char * msg ,
2017-05-11 07:11:46 +00:00
unsigned prio , unsigned duration ,
bool flush )
2018-11-22 14:45:52 +00:00
{
2019-02-21 09:23:21 +00:00
# if defined(HAVE_MENU) && defined(HAVE_MENU_WIDGETS)
if ( ! video_driver_has_widgets ( ) | | ! menu_widgets_task_msg_queue_push ( task , msg , prio , duration , flush ) )
# endif
runloop_msg_queue_push ( msg , prio , duration , flush , NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_INFO ) ;
2018-11-22 14:45:52 +00:00
}
void runloop_msg_queue_push ( const char * msg ,
unsigned prio , unsigned duration ,
bool flush ,
char * title ,
enum message_queue_icon icon , enum message_queue_category category )
2017-05-11 07:11:46 +00:00
{
runloop_ctx_msg_info_t msg_info ;
2019-02-21 09:23:21 +00:00
# if defined(HAVE_MENU) && defined(HAVE_MENU_WIDGETS)
2019-02-27 03:43:14 +00:00
float target_hz = 0.0 ;
rarch_environment_cb ( RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE , & target_hz ) ;
if ( video_driver_has_widgets ( ) & & menu_widgets_msg_queue_push ( msg ,
duration / target_hz * 1000 , title , icon , category , prio , flush ) )
2019-02-21 09:23:21 +00:00
return ;
# endif
2017-05-11 07:11:46 +00:00
# ifdef HAVE_THREADS
2017-10-30 03:27:56 +00:00
runloop_msg_queue_lock ( ) ;
2017-05-11 07:11:46 +00:00
# endif
if ( flush )
msg_queue_clear ( runloop_msg_queue ) ;
msg_info . msg = msg ;
msg_info . prio = prio ;
msg_info . duration = duration ;
msg_info . flush = flush ;
if ( runloop_msg_queue )
{
msg_queue_push ( runloop_msg_queue , msg_info . msg ,
2018-11-22 14:45:52 +00:00
msg_info . prio , msg_info . duration ,
title , icon , category ) ;
2017-05-11 07:11:46 +00:00
2018-04-30 18:33:05 +00:00
ui_companion_driver_msg_queue_push ( msg_info . msg ,
msg_info . prio , msg_info . duration , msg_info . flush ) ;
2017-05-11 07:11:46 +00:00
}
# ifdef HAVE_THREADS
2017-10-30 03:27:56 +00:00
runloop_msg_queue_unlock ( ) ;
2017-05-11 07:11:46 +00:00
# endif
}
2017-07-05 01:46:22 +00:00
void runloop_get_status ( bool * is_paused , bool * is_idle ,
2017-05-11 07:11:46 +00:00
bool * is_slowmotion , bool * is_perfcnt_enable )
{
* is_paused = runloop_paused ;
* is_idle = runloop_idle ;
* is_slowmotion = runloop_slowmotion ;
* is_perfcnt_enable = runloop_perfcnt_enable ;
}
bool runloop_msg_queue_pull ( const char * * ret )
{
# ifdef HAVE_THREADS
2017-10-30 03:27:56 +00:00
runloop_msg_queue_lock ( ) ;
2017-05-11 07:11:46 +00:00
# endif
2017-10-30 03:27:56 +00:00
if ( ! ret )
return false ;
2017-05-11 07:11:46 +00:00
* ret = msg_queue_pull ( runloop_msg_queue ) ;
# ifdef HAVE_THREADS
2017-10-30 03:27:56 +00:00
runloop_msg_queue_unlock ( ) ;
2017-05-11 07:11:46 +00:00
# endif
return true ;
}
2019-01-14 03:39:58 +00:00
# define bsv_movie_is_end_of_file() (bsv_movie_state.movie_end && bsv_movie_state.eof_exit)
2017-05-11 07:11:46 +00:00
/* Time to exit out of the main loop?
* Reasons for exiting :
* a ) Shutdown environment callback was invoked .
* b ) Quit key was pressed .
* c ) Frame count exceeds or equals maximum amount of frames to run .
* d ) Video driver no longer alive .
* e ) End of BSV movie and BSV EOF exit is true . ( TODO / FIXME - explain better )
*/
2019-01-14 03:39:58 +00:00
# define time_to_exit(quit_key_pressed) (runloop_shutdown_initiated || quit_key_pressed || !is_alive || bsv_movie_is_end_of_file() || ((runloop_max_frames != 0) && (frame_count >= runloop_max_frames)) || runloop_exec)
2017-05-11 07:11:46 +00:00
# define runloop_check_cheevos() (settings->bools.cheevos_enable && cheevos_loaded && (!cheats_are_enabled && !cheats_were_enabled))
2017-05-21 09:36:47 +00:00
# ifdef HAVE_NETWORKING
/* FIXME: This is an ugly way to tell Netplay this... */
# define runloop_netplay_pause() netplay_driver_ctl(RARCH_NETPLAY_CTL_PAUSE, NULL)
# else
# define runloop_netplay_pause() ((void)0)
# endif
2017-05-24 00:02:01 +00:00
# ifdef HAVE_MENU
static bool input_driver_toggle_button_combo (
2018-04-08 18:21:12 +00:00
unsigned mode , input_bits_t * p_input )
2017-05-24 00:02:01 +00:00
{
switch ( mode )
{
case INPUT_TOGGLE_DOWN_Y_L_R :
2017-12-05 11:07:35 +00:00
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_DOWN ) )
2017-05-24 00:02:01 +00:00
return false ;
2017-12-05 11:07:35 +00:00
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_Y ) )
2017-05-24 00:02:01 +00:00
return false ;
2017-12-05 11:07:35 +00:00
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_L ) )
2017-05-24 00:02:01 +00:00
return false ;
2017-12-05 11:07:35 +00:00
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_R ) )
2017-05-24 00:02:01 +00:00
return false ;
break ;
case INPUT_TOGGLE_L3_R3 :
2017-12-05 11:07:35 +00:00
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_L3 ) )
2017-05-24 00:02:01 +00:00
return false ;
2017-12-05 11:07:35 +00:00
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_R3 ) )
2017-05-24 00:02:01 +00:00
return false ;
break ;
case INPUT_TOGGLE_L1_R1_START_SELECT :
2017-12-05 11:07:35 +00:00
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_START ) )
2017-05-24 00:02:01 +00:00
return false ;
2017-12-05 11:07:35 +00:00
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_SELECT ) )
2017-05-24 00:02:01 +00:00
return false ;
2017-12-05 11:07:35 +00:00
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_L ) )
2017-05-24 00:02:01 +00:00
return false ;
2017-12-05 11:07:35 +00:00
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_R ) )
2017-05-24 00:02:01 +00:00
return false ;
break ;
case INPUT_TOGGLE_START_SELECT :
2017-12-05 11:07:35 +00:00
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_START ) )
2017-05-24 00:02:01 +00:00
return false ;
2017-12-05 11:07:35 +00:00
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_SELECT ) )
2017-05-24 00:02:01 +00:00
return false ;
break ;
2018-09-30 22:20:45 +00:00
case INPUT_TOGGLE_L3_R :
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_L3 ) )
return false ;
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_R ) )
return false ;
break ;
2018-09-30 23:36:31 +00:00
case INPUT_TOGGLE_L_R :
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_L ) )
return false ;
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_R ) )
return false ;
break ;
2019-01-28 16:43:57 +00:00
case INPUT_TOGGLE_DOWN_SELECT :
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_DOWN ) )
return false ;
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_SELECT ) )
return false ;
break ;
2018-12-19 19:53:17 +00:00
case INPUT_TOGGLE_HOLD_START :
{
static rarch_timer_t timer = { 0 } ;
if ( ! BIT256_GET_PTR ( p_input , RETRO_DEVICE_ID_JOYPAD_START ) )
{
/* timer only runs while start is held down */
rarch_timer_end ( & timer ) ;
return false ;
}
if ( ! rarch_timer_is_running ( & timer ) )
{
/* user started holding down the start button, start the timer */
rarch_timer_begin ( & timer , HOLD_START_DELAY_SEC ) ;
}
rarch_timer_tick ( & timer ) ;
if ( ! timer . timer_end & & rarch_timer_has_expired ( & timer ) )
{
/* start has been held down long enough, stop timer and enter menu */
rarch_timer_end ( & timer ) ;
return true ;
}
return false ;
}
2017-05-24 00:02:01 +00:00
default :
case INPUT_TOGGLE_NONE :
return false ;
}
2017-07-05 01:46:22 +00:00
2017-05-24 00:02:01 +00:00
return true ;
}
# endif
2017-05-11 07:11:46 +00:00
static enum runloop_state runloop_check_state (
settings_t * settings ,
2017-05-21 19:55:20 +00:00
bool input_nonblock_state ,
2019-01-12 16:58:35 +00:00
bool runloop_is_paused ,
float fastforward_ratio ,
2017-05-11 07:11:46 +00:00
unsigned * sleep_ms )
{
2018-04-08 18:21:12 +00:00
input_bits_t current_input ;
2017-12-31 17:02:14 +00:00
# ifdef HAVE_MENU
2018-04-08 18:21:12 +00:00
static input_bits_t last_input = { { 0 } } ;
2017-12-31 17:02:14 +00:00
# endif
2019-02-25 18:12:50 +00:00
static bool old_quit_key = false ;
static bool quit_key = false ;
static bool trig_quit_key = false ;
static retro_time_t quit_key_time = 0 ;
static bool runloop_exec = false ;
static bool old_focus = true ;
bool is_focused = false ;
bool is_alive = false ;
uint64_t frame_count = 0 ;
bool focused = true ;
bool pause_nonactive = settings - > bools . pause_nonactive ;
2019-02-27 15:47:39 +00:00
bool rarch_is_initialized = rarch_is_inited ;
2019-02-25 18:12:50 +00:00
bool fs_toggle_triggered = false ;
2017-05-21 21:53:39 +00:00
# ifdef HAVE_MENU
2019-02-25 18:12:50 +00:00
bool menu_driver_binding_state = menu_driver_is_binding_state ( ) ;
bool menu_is_alive = menu_driver_is_alive ( ) ;
unsigned menu_toggle_gamepad_combo = settings - > uints . input_menu_toggle_gamepad_combo ;
2019-01-06 22:21:15 +00:00
# ifdef HAVE_EASTEREGG
2019-02-25 18:12:50 +00:00
static uint64_t seq = 0 ;
2019-01-06 22:21:15 +00:00
# endif
2018-04-08 22:30:45 +00:00
# endif
2018-11-07 18:25:26 +00:00
# ifdef HAVE_LIBNX
2019-01-12 16:58:35 +00:00
/* Should be called once per frame */
if ( ! appletMainLoop ( ) )
2018-11-07 18:25:26 +00:00
return RUNLOOP_STATE_QUIT ;
# endif
2018-04-08 22:30:45 +00:00
BIT256_CLEAR_ALL_PTR ( & current_input ) ;
2017-11-24 11:19:17 +00:00
2018-04-08 22:30:45 +00:00
# ifdef HAVE_MENU
2017-12-05 08:22:33 +00:00
if ( menu_is_alive & & ! ( settings - > bools . menu_unified_controls & & ! menu_input_dialog_get_display_kb ( ) ) )
2018-04-30 18:33:05 +00:00
input_menu_keys_pressed ( settings , & current_input ) ;
2017-11-24 11:19:17 +00:00
else
2017-12-17 03:11:56 +00:00
# endif
2018-04-30 18:33:05 +00:00
input_keys_pressed ( settings , & current_input ) ;
2017-11-24 11:19:17 +00:00
2017-05-21 18:42:46 +00:00
# ifdef HAVE_MENU
2017-12-31 17:02:14 +00:00
last_input = current_input ;
2017-05-24 00:02:01 +00:00
if (
2019-01-12 16:58:35 +00:00
( ( menu_toggle_gamepad_combo ! = INPUT_TOGGLE_NONE ) & &
2017-05-24 00:02:01 +00:00
input_driver_toggle_button_combo (
2019-01-12 16:58:35 +00:00
menu_toggle_gamepad_combo , & last_input ) ) )
2017-12-05 11:07:35 +00:00
BIT256_SET ( current_input , RARCH_MENU_TOGGLE ) ;
2017-05-21 18:42:46 +00:00
# endif
2017-05-21 21:53:39 +00:00
if ( input_driver_flushing_input )
2017-07-05 01:46:22 +00:00
{
input_driver_flushing_input = false ;
2017-12-05 12:15:15 +00:00
if ( bits_any_set ( current_input . data , ARRAY_SIZE ( current_input . data ) ) )
2017-05-21 21:53:39 +00:00
{
2017-12-05 11:07:35 +00:00
BIT256_CLEAR_ALL ( current_input ) ;
2019-01-12 16:58:35 +00:00
if ( runloop_is_paused )
2017-12-05 11:07:35 +00:00
BIT256_SET ( current_input , RARCH_PAUSE_TOGGLE ) ;
2017-07-05 01:46:22 +00:00
input_driver_flushing_input = true ;
2017-05-21 21:53:39 +00:00
}
}
2018-07-14 03:34:03 +00:00
if ( ! video_driver_is_threaded ( ) )
{
const ui_application_t * application =
ui_companion_driver_get_application_ptr ( ) ;
if ( application )
application - > process_events ( ) ;
}
2017-05-21 18:43:55 +00:00
video_driver_get_status ( & frame_count , & is_alive , & is_focused ) ;
2017-06-10 21:26:41 +00:00
# ifdef HAVE_MENU
if ( menu_driver_binding_state )
2017-12-05 11:07:35 +00:00
BIT256_CLEAR_ALL ( current_input ) ;
2017-06-10 21:26:41 +00:00
# endif
2017-05-20 12:17:14 +00:00
# ifdef HAVE_OVERLAY
2017-05-21 10:09:24 +00:00
/* Check next overlay */
{
static bool old_should_check_next_overlay = false ;
2017-12-05 11:07:35 +00:00
bool should_check_next_overlay = BIT256_GET (
2017-05-21 10:09:24 +00:00
current_input , RARCH_OVERLAY_NEXT ) ;
if ( should_check_next_overlay & & ! old_should_check_next_overlay )
command_event ( CMD_EVENT_OVERLAY_NEXT , NULL ) ;
old_should_check_next_overlay = should_check_next_overlay ;
}
2017-05-20 12:17:14 +00:00
# endif
2017-05-11 07:11:46 +00:00
2017-05-21 14:36:08 +00:00
/* Check fullscreen toggle */
2017-05-11 07:11:46 +00:00
{
2019-01-12 17:10:22 +00:00
static bool old_fs_toggle_pressed = false ;
bool fs_toggle_pressed = BIT256_GET (
2017-05-21 14:36:08 +00:00
current_input , RARCH_FULLSCREEN_TOGGLE_KEY ) ;
2019-01-12 17:10:22 +00:00
fs_toggle_triggered = fs_toggle_pressed & & ! old_fs_toggle_pressed ;
2017-05-21 14:36:08 +00:00
if ( fs_toggle_triggered )
{
2019-01-12 16:58:35 +00:00
bool fullscreen_toggled = ! runloop_is_paused
2017-05-19 14:26:00 +00:00
# ifdef HAVE_MENU
2017-05-21 14:36:08 +00:00
| | menu_is_alive ;
2017-06-21 01:53:46 +00:00
# else
2019-01-14 04:25:04 +00:00
;
2017-05-19 14:26:00 +00:00
# endif
2017-05-11 07:11:46 +00:00
2017-05-21 14:36:08 +00:00
if ( fullscreen_toggled )
command_event ( CMD_EVENT_FULLSCREEN_TOGGLE , NULL ) ;
}
old_fs_toggle_pressed = fs_toggle_pressed ;
2017-05-11 07:11:46 +00:00
}
2017-05-21 11:06:48 +00:00
/* Check mouse grab toggle */
{
static bool old_pressed = false ;
2017-12-05 11:07:35 +00:00
bool pressed = BIT256_GET (
2017-05-21 11:06:48 +00:00
current_input , RARCH_GRAB_MOUSE_TOGGLE ) ;
if ( pressed & & ! old_pressed )
2017-08-12 22:43:16 +00:00
command_event ( CMD_EVENT_GRAB_MOUSE_TOGGLE , NULL ) ;
2017-05-21 11:06:48 +00:00
old_pressed = pressed ;
}
2017-05-11 07:11:46 +00:00
# ifdef HAVE_OVERLAY
{
2017-05-21 10:57:28 +00:00
static char prev_overlay_restore = false ;
if ( input_keyboard_ctl (
RARCH_INPUT_KEYBOARD_CTL_IS_LINEFEED_ENABLED , NULL ) )
{
prev_overlay_restore = false ;
2017-05-11 07:11:46 +00:00
command_event ( CMD_EVENT_OVERLAY_INIT , NULL ) ;
2017-05-21 10:57:28 +00:00
}
else if ( prev_overlay_restore )
{
if ( ! settings - > bools . input_overlay_hide_in_menu )
command_event ( CMD_EVENT_OVERLAY_INIT , NULL ) ;
prev_overlay_restore = false ;
}
2017-05-11 07:11:46 +00:00
}
# endif
2017-05-21 11:50:59 +00:00
/* Check quit key */
2017-05-11 07:11:46 +00:00
{
2019-01-18 03:58:44 +00:00
quit_key = BIT256_GET (
2019-01-14 08:04:37 +00:00
current_input , RARCH_QUIT_KEY ) ;
2019-01-18 03:58:44 +00:00
trig_quit_key = quit_key & & ! old_quit_key ;
2017-05-21 11:50:59 +00:00
old_quit_key = quit_key ;
2019-02-25 18:12:50 +00:00
/* Check double press if enabled */
if ( trig_quit_key & & settings - > bools . quit_press_twice )
{
2019-02-27 03:43:14 +00:00
retro_time_t cur_time ;
float target_hz = 0.0 ;
rarch_environment_cb ( RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE , & target_hz ) ;
cur_time = cpu_features_get_time_usec ( ) ;
2019-02-25 18:12:50 +00:00
trig_quit_key = trig_quit_key & & ( cur_time - quit_key_time < QUIT_DELAY_USEC ) ;
quit_key_time = cur_time ;
if ( ! trig_quit_key )
2019-02-27 03:43:14 +00:00
runloop_msg_queue_push ( msg_hash_to_str ( MSG_PRESS_AGAIN_TO_QUIT ) , 1 ,
QUIT_DELAY_USEC * target_hz / 1000000 ,
true , NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_INFO ) ;
2019-02-25 18:12:50 +00:00
}
2017-05-21 11:50:59 +00:00
if ( time_to_exit ( trig_quit_key ) )
2017-05-11 07:11:46 +00:00
{
2018-08-19 03:09:40 +00:00
if ( ( runloop_max_frames ! = 0 ) & & ( frame_count > = runloop_max_frames ) )
{
if ( runloop_max_frames_screenshot )
{
const char * screenshot_path = NULL ;
bool fullpath = false ;
if ( string_is_empty ( runloop_max_frames_screenshot_path ) )
screenshot_path = path_get ( RARCH_PATH_BASENAME ) ;
else
{
fullpath = true ;
screenshot_path = runloop_max_frames_screenshot_path ;
}
RARCH_LOG ( " Taking a screenshot before exiting... \n " ) ;
/* Take a screenshot before we exit. */
if ( ! take_screenshot ( screenshot_path , false ,
video_driver_cached_frame_has_valid_framebuffer ( ) , fullpath , false ) )
{
RARCH_ERR ( " Could not take a screenshot before exiting. \n " ) ;
}
}
}
2017-05-21 11:50:59 +00:00
if ( runloop_exec )
runloop_exec = false ;
if ( runloop_core_shutdown_initiated & & settings - > bools . load_dummy_on_core_shutdown )
{
content_ctx_info_t content_info ;
2017-05-11 07:11:46 +00:00
2017-05-21 11:50:59 +00:00
content_info . argc = 0 ;
content_info . argv = NULL ;
content_info . args = NULL ;
content_info . environ_get = NULL ;
if ( ! task_push_start_dummy_core ( & content_info ) )
2019-01-14 04:25:04 +00:00
goto quit ;
2017-05-11 07:11:46 +00:00
2017-05-21 11:50:59 +00:00
/* Loads dummy core instead of exiting RetroArch completely.
* Aborts core shutdown if invoked . */
2019-01-10 01:35:03 +00:00
rarch_ctl ( RARCH_CTL_UNSET_SHUTDOWN , NULL ) ;
2017-05-21 11:50:59 +00:00
runloop_core_shutdown_initiated = false ;
}
else
2019-01-14 04:25:04 +00:00
goto quit ;
2017-05-11 07:11:46 +00:00
}
}
2018-11-22 14:45:52 +00:00
# if defined(HAVE_MENU)
2019-02-14 10:58:27 +00:00
menu_animation_update ( ) ;
2019-02-08 19:02:45 +00:00
2019-02-21 09:23:21 +00:00
# ifdef HAVE_MENU_WIDGETS
menu_widgets_iterate ( ) ;
# endif
2017-05-19 14:29:11 +00:00
if ( menu_is_alive )
2017-05-11 07:11:46 +00:00
{
2019-01-12 16:58:35 +00:00
enum menu_action action ;
2018-04-08 18:21:12 +00:00
static input_bits_t old_input = { { 0 } } ;
2019-02-03 23:49:35 +00:00
static enum menu_action
2019-01-12 16:58:35 +00:00
old_action = MENU_ACTION_CANCEL ;
bool focused = false ;
input_bits_t trigger_input = current_input ;
global_t * global = global_get_ptr ( ) ;
2018-07-25 23:19:14 +00:00
2017-05-11 07:11:46 +00:00
menu_ctx_iterate_t iter ;
2017-05-29 18:30:01 +00:00
retro_ctx . poll_cb ( ) ;
2017-05-11 07:11:46 +00:00
2019-01-12 16:58:35 +00:00
bits_clear_bits ( trigger_input . data , old_input . data ,
ARRAY_SIZE ( trigger_input . data ) ) ;
2017-11-23 23:04:09 +00:00
2019-01-12 16:58:35 +00:00
action = ( enum menu_action ) menu_event ( & current_input , & trigger_input ) ;
focused = pause_nonactive ? is_focused : true ;
focused = focused & & ! ui_companion_is_on_foreground ( ) ;
2017-05-11 07:11:46 +00:00
2019-01-12 16:58:35 +00:00
iter . action = action ;
2017-05-11 07:11:46 +00:00
2019-01-12 16:58:35 +00:00
if ( global )
{
if ( action = = old_action )
{
retro_time_t press_time = cpu_features_get_time_usec ( ) ;
if ( action = = MENU_ACTION_NOOP )
global - > menu . noop_press_time = press_time - global - > menu . noop_start_time ;
else
global - > menu . action_press_time = press_time - global - > menu . action_start_time ;
}
else
2018-07-25 23:19:14 +00:00
{
2019-01-12 16:58:35 +00:00
if ( action = = MENU_ACTION_NOOP )
2018-07-25 23:19:14 +00:00
{
2019-01-12 16:58:35 +00:00
global - > menu . noop_start_time = cpu_features_get_time_usec ( ) ;
global - > menu . noop_press_time = 0 ;
if ( global - > menu . prev_action = = old_action )
global - > menu . action_start_time = global - > menu . prev_start_time ;
2018-07-25 23:19:14 +00:00
else
2019-01-12 16:58:35 +00:00
global - > menu . action_start_time = cpu_features_get_time_usec ( ) ;
2018-07-25 23:19:14 +00:00
}
else
{
2019-01-12 16:58:35 +00:00
if ( global - > menu . prev_action = = action & &
global - > menu . noop_press_time < 200000 ) /* 250ms */
2018-07-25 23:19:14 +00:00
{
2019-01-12 16:58:35 +00:00
global - > menu . action_start_time = global - > menu . prev_start_time ;
global - > menu . action_press_time = cpu_features_get_time_usec ( ) - global - > menu . action_start_time ;
2018-07-25 23:19:14 +00:00
}
else
{
2019-01-12 16:58:35 +00:00
global - > menu . prev_start_time = cpu_features_get_time_usec ( ) ;
global - > menu . prev_action = action ;
global - > menu . action_press_time = 0 ;
2018-07-25 23:19:14 +00:00
}
}
}
2019-01-12 16:58:35 +00:00
}
2018-07-25 23:19:14 +00:00
2019-01-12 16:58:35 +00:00
if ( ! menu_driver_iterate ( & iter ) )
rarch_menu_running_finished ( ) ;
2017-05-21 19:19:07 +00:00
2019-01-12 16:58:35 +00:00
if ( focused | | ! runloop_idle )
{
bool libretro_running = menu_display_libretro_running (
rarch_is_initialized ,
( current_core_type = = CORE_TYPE_DUMMY ) ) ;
menu_driver_render ( runloop_idle , rarch_is_initialized ,
( current_core_type = = CORE_TYPE_DUMMY )
)
;
if ( settings - > bools . audio_enable_menu & &
! libretro_running )
audio_driver_menu_sample ( ) ;
2019-01-05 23:33:29 +00:00
# ifdef HAVE_EASTEREGG
2019-01-12 16:58:35 +00:00
{
bool library_name_is_empty = string_is_empty ( runloop_system . info . library_name ) ;
2019-01-05 23:33:29 +00:00
2019-01-12 16:58:35 +00:00
if ( library_name_is_empty & & trigger_input . data [ 0 ] )
{
seq | = trigger_input . data [ 0 ] & 0xF0 ;
2019-01-05 23:33:29 +00:00
2019-01-12 16:58:35 +00:00
if ( seq = = 1157460427127406720ULL )
{
content_ctx_info_t content_info ;
content_info . argc = 0 ;
content_info . argv = NULL ;
content_info . args = NULL ;
content_info . environ_get = NULL ;
task_push_start_builtin_core (
& content_info ,
CORE_TYPE_GONG , NULL , NULL ) ;
2019-01-05 23:33:29 +00:00
}
2019-01-12 16:58:35 +00:00
seq < < = 8 ;
2019-01-05 23:33:29 +00:00
}
2019-01-12 16:58:35 +00:00
else if ( ! library_name_is_empty )
seq = 0 ;
2018-04-28 22:06:54 +00:00
}
2019-01-12 16:58:35 +00:00
# endif
}
2017-05-29 18:30:01 +00:00
2019-01-12 16:58:35 +00:00
old_input = current_input ;
old_action = action ;
2017-05-29 18:30:01 +00:00
2019-01-12 16:58:35 +00:00
if ( ! focused )
return RUNLOOP_STATE_POLLED_AND_SLEEP ;
2017-05-29 18:30:01 +00:00
if ( runloop_idle )
return RUNLOOP_STATE_POLLED_AND_SLEEP ;
2017-05-11 07:11:46 +00:00
}
2017-05-29 18:30:01 +00:00
else
2017-05-11 07:11:46 +00:00
# endif
2019-01-05 23:33:29 +00:00
{
2019-01-06 22:21:15 +00:00
# if defined(HAVE_MENU) && defined(HAVE_EASTEREGG)
2019-01-05 23:33:29 +00:00
seq = 0 ;
2017-05-11 07:11:46 +00:00
# endif
2017-05-29 18:30:01 +00:00
if ( runloop_idle )
return RUNLOOP_STATE_SLEEP ;
2019-01-05 23:33:29 +00:00
}
2017-05-11 07:11:46 +00:00
2017-05-21 11:39:29 +00:00
/* Check game focus toggle */
{
static bool old_pressed = false ;
2017-12-05 11:07:35 +00:00
bool pressed = BIT256_GET (
2017-05-21 11:39:29 +00:00
current_input , RARCH_GAME_FOCUS_TOGGLE ) ;
if ( pressed & & ! old_pressed )
command_event ( CMD_EVENT_GAME_FOCUS_TOGGLE , ( void * ) ( intptr_t ) 0 ) ;
old_pressed = pressed ;
}
2017-05-11 07:11:46 +00:00
2019-02-28 20:54:46 +00:00
/* Check if we have pressed the UI companion toggle button */
2018-04-30 18:33:05 +00:00
{
static bool old_pressed = false ;
bool pressed = BIT256_GET (
current_input , RARCH_UI_COMPANION_TOGGLE ) ;
if ( pressed & & ! old_pressed )
command_event ( CMD_EVENT_UI_COMPANION_TOGGLE , ( void * ) ( intptr_t ) 0 ) ;
old_pressed = pressed ;
}
2017-05-11 07:11:46 +00:00
# ifdef HAVE_MENU
2019-02-28 20:54:46 +00:00
/* Check if we have pressed the menu toggle button */
2017-05-11 07:11:46 +00:00
{
2017-05-21 11:54:17 +00:00
static bool old_pressed = false ;
2019-01-07 19:26:13 +00:00
char * menu_driver = settings - > arrays . menu_driver ;
2017-12-05 11:07:35 +00:00
bool pressed = BIT256_GET (
2019-01-07 19:26:13 +00:00
current_input , RARCH_MENU_TOGGLE ) & &
2019-01-14 04:25:04 +00:00
! string_is_equal ( menu_driver , " null " ) ;
2017-05-21 11:54:17 +00:00
2017-12-17 16:21:51 +00:00
if ( menu_event_kb_is_set ( RETROK_F1 ) = = 1 )
{
if ( menu_driver_is_alive ( ) )
{
2019-02-03 23:49:35 +00:00
if ( rarch_is_initialized & &
2019-01-12 16:58:35 +00:00
( current_core_type ! = CORE_TYPE_DUMMY ) )
2017-12-17 16:21:51 +00:00
{
rarch_menu_running_finished ( ) ;
menu_event_kb_set ( false , RETROK_F1 ) ;
}
}
}
else if ( ( ! menu_event_kb_is_set ( RETROK_F1 ) & &
( pressed & & ! old_pressed ) ) | |
( current_core_type = = CORE_TYPE_DUMMY ) )
{
if ( menu_driver_is_alive ( ) )
{
2019-02-03 23:49:35 +00:00
if ( rarch_is_initialized & &
2019-01-12 16:58:35 +00:00
( current_core_type ! = CORE_TYPE_DUMMY ) )
2017-12-17 16:21:51 +00:00
rarch_menu_running_finished ( ) ;
}
else
{
menu_display_toggle_set_reason ( MENU_TOGGLE_REASON_USER ) ;
rarch_menu_running ( ) ;
}
}
else
menu_event_kb_set ( false , RETROK_F1 ) ;
2017-05-21 11:54:17 +00:00
old_pressed = pressed ;
2017-05-11 07:11:46 +00:00
}
2019-03-09 21:03:17 +00:00
/* Check if we have pressed the "send debug info" button.
* Must press 3 times in a row to activate , but it will
* alert the user of this with each press of the hotkey . */
{
static uint32_t debug_seq = 0 ;
static bool old_pressed = false ;
static bool old_any_pressed = false ;
int any_i ;
bool any_pressed = false ;
bool pressed = BIT256_GET ( current_input , RARCH_SEND_DEBUG_INFO ) ;
for ( any_i = 0 ; any_i < ARRAY_SIZE ( current_input . data ) ; any_i + + )
{
if ( current_input . data [ any_i ] )
{
any_pressed = true ;
break ;
}
}
if ( pressed & & ! old_pressed )
debug_seq | = pressed ? 1 : 0 ;
switch ( debug_seq )
{
case 1 : /* pressed hotkey one time */
runloop_msg_queue_push (
msg_hash_to_str ( MSG_PRESS_TWO_MORE_TIMES_TO_SEND_DEBUG_INFO ) ,
2 , 180 , true ,
NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_INFO ) ;
break ;
case 3 : /* pressed hotkey two times */
runloop_msg_queue_push (
msg_hash_to_str ( MSG_PRESS_ONE_MORE_TIME_TO_SEND_DEBUG_INFO ) ,
2 , 180 , true ,
NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_INFO ) ;
break ;
case 7 : /* pressed hotkey third and final time */
debug_seq = 0 ;
command_event ( CMD_EVENT_SEND_DEBUG_INFO , NULL ) ;
break ;
}
if ( any_pressed & & ! old_any_pressed )
{
debug_seq < < = 1 ;
if ( debug_seq > 7 )
debug_seq = 0 ;
}
old_pressed = pressed ;
old_any_pressed = any_pressed ;
}
/* Check if we have pressed the FPS toggle button */
{
static bool old_pressed = false ;
bool pressed = BIT256_GET (
current_input , RARCH_FPS_TOGGLE ) ;
if ( pressed & & ! old_pressed )
command_event ( CMD_EVENT_FPS_TOGGLE , NULL ) ;
old_pressed = pressed ;
}
2019-03-09 22:48:03 +00:00
/* Check if we have pressed the netplay host toggle button */
{
static bool old_pressed = false ;
bool pressed = BIT256_GET (
current_input , RARCH_NETPLAY_HOST_TOGGLE ) ;
if ( pressed & & ! old_pressed )
command_event ( CMD_EVENT_NETPLAY_HOST_TOGGLE , NULL ) ;
old_pressed = pressed ;
}
2017-05-19 14:26:00 +00:00
if ( menu_driver_is_alive ( ) )
2017-05-11 07:11:46 +00:00
{
2019-01-12 16:58:35 +00:00
if ( ! settings - > bools . menu_throttle_framerate & & ! fastforward_ratio )
2017-05-11 07:11:46 +00:00
return RUNLOOP_STATE_MENU_ITERATE ;
return RUNLOOP_STATE_END ;
}
# endif
2017-05-17 06:51:49 +00:00
if ( pause_nonactive )
2017-05-11 07:11:46 +00:00
focused = is_focused ;
2019-02-28 20:54:46 +00:00
/* Check if we have pressed the screenshot toggle button */
2017-05-21 11:06:48 +00:00
{
static bool old_pressed = false ;
2017-12-05 11:07:35 +00:00
bool pressed = BIT256_GET (
2017-05-21 11:06:48 +00:00
current_input , RARCH_SCREENSHOT ) ;
if ( pressed & & old_pressed )
command_event ( CMD_EVENT_TAKE_SCREENSHOT , NULL ) ;
2017-05-11 07:11:46 +00:00
2017-05-21 11:06:48 +00:00
old_pressed = pressed ;
}
2017-05-11 07:11:46 +00:00
2019-02-28 20:54:46 +00:00
/* Check if we have pressed the audio mute toggle button */
2017-05-11 07:11:46 +00:00
{
2017-05-21 11:06:48 +00:00
static bool old_pressed = false ;
2017-12-05 11:07:35 +00:00
bool pressed = BIT256_GET (
2017-05-21 11:06:48 +00:00
current_input , RARCH_MUTE ) ;
if ( pressed & & ! old_pressed )
command_event ( CMD_EVENT_AUDIO_MUTE_TOGGLE , NULL ) ;
old_pressed = pressed ;
}
2019-02-28 20:54:46 +00:00
/* Check if we have pressed the OSK toggle button */
2017-05-21 11:06:48 +00:00
{
static bool old_pressed = false ;
2017-12-05 11:07:35 +00:00
bool pressed = BIT256_GET ( current_input , RARCH_OSK ) ;
2017-05-21 11:06:48 +00:00
if ( pressed & & ! old_pressed )
{
if ( input_keyboard_ctl (
RARCH_INPUT_KEYBOARD_CTL_IS_LINEFEED_ENABLED , NULL ) )
input_keyboard_ctl (
RARCH_INPUT_KEYBOARD_CTL_UNSET_LINEFEED_ENABLED , NULL ) ;
else
input_keyboard_ctl (
RARCH_INPUT_KEYBOARD_CTL_SET_LINEFEED_ENABLED , NULL ) ;
}
old_pressed = pressed ;
2017-05-11 07:11:46 +00:00
}
2019-02-28 20:54:46 +00:00
/* Check if we have pressed the recording toggle button */
2018-09-18 06:51:35 +00:00
{
static bool old_pressed = false ;
bool pressed = BIT256_GET (
current_input , RARCH_RECORDING_TOGGLE ) ;
if ( pressed & & ! old_pressed )
2018-09-27 17:06:39 +00:00
{
if ( recording_is_enabled ( ) )
command_event ( CMD_EVENT_RECORD_DEINIT , NULL ) ;
else
command_event ( CMD_EVENT_RECORD_INIT , NULL ) ;
}
2018-09-18 06:51:35 +00:00
old_pressed = pressed ;
}
2019-02-28 20:54:46 +00:00
/* Check if we have pressed the streaming toggle button */
2018-09-18 06:51:35 +00:00
{
static bool old_pressed = false ;
bool pressed = BIT256_GET (
current_input , RARCH_STREAMING_TOGGLE ) ;
if ( pressed & & ! old_pressed )
2018-09-27 17:06:39 +00:00
{
if ( streaming_is_enabled ( ) )
command_event ( CMD_EVENT_RECORD_DEINIT , NULL ) ;
else
{
streaming_set_state ( true ) ;
command_event ( CMD_EVENT_RECORD_INIT , NULL ) ;
}
}
2018-09-18 06:51:35 +00:00
old_pressed = pressed ;
}
2017-12-05 11:07:35 +00:00
if ( BIT256_GET ( current_input , RARCH_VOLUME_UP ) )
2017-05-11 07:11:46 +00:00
command_event ( CMD_EVENT_VOLUME_UP , NULL ) ;
2017-12-05 11:07:35 +00:00
else if ( BIT256_GET ( current_input , RARCH_VOLUME_DOWN ) )
2017-05-11 07:11:46 +00:00
command_event ( CMD_EVENT_VOLUME_DOWN , NULL ) ;
# ifdef HAVE_NETWORKING
2017-05-21 12:18:10 +00:00
/* Check Netplay */
2017-05-21 10:06:08 +00:00
{
2017-05-21 12:18:10 +00:00
static bool old_netplay_watch = false ;
2017-12-05 11:07:35 +00:00
bool netplay_watch = BIT256_GET (
2017-05-21 12:18:10 +00:00
current_input , RARCH_NETPLAY_GAME_WATCH ) ;
if ( netplay_watch & & ! old_netplay_watch )
2017-05-21 10:06:08 +00:00
netplay_driver_ctl ( RARCH_NETPLAY_CTL_GAME_WATCH , NULL ) ;
2017-05-21 12:18:10 +00:00
old_netplay_watch = netplay_watch ;
2017-05-21 10:06:08 +00:00
}
2017-05-11 07:11:46 +00:00
# endif
2019-02-28 20:54:46 +00:00
/* Check if we have pressed the pause button */
2017-05-21 10:59:36 +00:00
{
2017-05-21 14:31:05 +00:00
static bool old_frameadvance = false ;
2017-05-21 10:59:36 +00:00
static bool old_pause_pressed = false ;
2017-05-21 14:31:05 +00:00
bool check_is_oneshot = true ;
2017-12-05 11:07:35 +00:00
bool frameadvance_pressed = BIT256_GET (
2017-05-21 14:31:05 +00:00
current_input , RARCH_FRAMEADVANCE ) ;
2017-12-05 11:07:35 +00:00
bool pause_pressed = BIT256_GET (
2017-05-21 10:59:36 +00:00
current_input , RARCH_PAUSE_TOGGLE ) ;
2017-05-21 14:31:05 +00:00
bool trig_frameadvance = frameadvance_pressed & & ! old_frameadvance ;
2017-05-21 10:59:36 +00:00
/* Check if libretro pause key was pressed. If so, pause or
* unpause the libretro core . */
/* FRAMEADVANCE will set us into pause mode. */
2019-01-12 16:58:35 +00:00
pause_pressed | = ! runloop_is_paused & & trig_frameadvance ;
2017-05-21 10:59:36 +00:00
if ( focused & & pause_pressed & & ! old_pause_pressed )
command_event ( CMD_EVENT_PAUSE_TOGGLE , NULL ) ;
else if ( focused & & ! old_focus )
command_event ( CMD_EVENT_UNPAUSE , NULL ) ;
else if ( ! focused & & old_focus )
command_event ( CMD_EVENT_PAUSE , NULL ) ;
old_focus = focused ;
2017-07-05 01:46:22 +00:00
old_pause_pressed = pause_pressed ;
2017-05-21 14:31:05 +00:00
old_frameadvance = frameadvance_pressed ;
2017-05-11 07:11:46 +00:00
2019-01-12 16:58:35 +00:00
if ( runloop_is_paused )
2017-05-11 07:11:46 +00:00
{
2017-07-05 01:46:22 +00:00
check_is_oneshot = trig_frameadvance | |
2017-12-05 11:07:35 +00:00
BIT256_GET ( current_input , RARCH_REWIND ) ;
2017-05-21 14:31:05 +00:00
2017-05-21 14:36:08 +00:00
if ( fs_toggle_triggered )
2017-05-21 11:06:48 +00:00
{
command_event ( CMD_EVENT_FULLSCREEN_TOGGLE , NULL ) ;
if ( ! runloop_idle )
video_driver_cached_frame ( ) ;
}
}
2017-05-21 14:31:05 +00:00
if ( ! check_is_oneshot )
return RUNLOOP_STATE_SLEEP ;
2017-05-11 07:11:46 +00:00
}
2017-05-21 14:31:05 +00:00
if ( ! focused )
return RUNLOOP_STATE_SLEEP ;
2019-02-28 20:54:46 +00:00
/* Check if we have pressed the fast forward button */
2017-05-11 07:11:46 +00:00
/* To avoid continous switching if we hold the button down, we require
* that the button must go from pressed to unpressed back to pressed
* to be able to toggle between then .
*/
{
2017-05-21 11:32:36 +00:00
static bool old_button_state = false ;
static bool old_hold_button_state = false ;
2017-12-05 11:07:35 +00:00
bool new_button_state = BIT256_GET (
2017-05-21 11:32:36 +00:00
current_input , RARCH_FAST_FORWARD_KEY ) ;
2017-12-05 11:07:35 +00:00
bool new_hold_button_state = BIT256_GET (
2017-05-21 11:32:36 +00:00
current_input , RARCH_FAST_FORWARD_HOLD_KEY ) ;
if ( new_button_state & & ! old_button_state )
{
2018-04-10 05:19:27 +00:00
if ( input_nonblock_state )
{
2017-05-21 11:32:36 +00:00
input_driver_unset_nonblock_state ( ) ;
2019-01-12 16:58:35 +00:00
runloop_fastmotion = false ;
2018-08-04 22:34:10 +00:00
fastforward_after_frames = 1 ;
2017-11-18 15:48:53 +00:00
}
2018-04-10 05:19:27 +00:00
else
{
2017-05-21 11:32:36 +00:00
input_driver_set_nonblock_state ( ) ;
2017-11-18 15:48:53 +00:00
runloop_fastmotion = true ;
}
2017-05-21 11:32:36 +00:00
driver_set_nonblock_state ( ) ;
}
else if ( old_hold_button_state ! = new_hold_button_state )
{
2018-04-10 05:19:27 +00:00
if ( new_hold_button_state )
{
2017-05-21 11:32:36 +00:00
input_driver_set_nonblock_state ( ) ;
2017-11-18 15:48:53 +00:00
runloop_fastmotion = true ;
}
2018-04-10 05:19:27 +00:00
else
{
2017-05-21 11:32:36 +00:00
input_driver_unset_nonblock_state ( ) ;
2019-01-12 16:58:35 +00:00
runloop_fastmotion = false ;
2018-08-04 22:34:10 +00:00
fastforward_after_frames = 1 ;
2017-11-18 15:48:53 +00:00
}
2017-05-21 11:32:36 +00:00
driver_set_nonblock_state ( ) ;
}
2017-11-26 21:53:42 +00:00
/* Display the fast forward state to the user, if needed. */
if ( runloop_fastmotion )
2019-02-08 06:26:43 +00:00
runloop_msg_queue_push (
msg_hash_to_str ( MSG_FAST_FORWARD ) , 1 , 1 , false , NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_INFO ) ;
2017-11-18 15:48:53 +00:00
2017-05-21 11:32:36 +00:00
old_button_state = new_button_state ;
old_hold_button_state = new_hold_button_state ;
2017-05-11 07:11:46 +00:00
}
2019-02-28 20:54:46 +00:00
/* Check if we have pressed any of the state slot buttons */
2017-05-21 10:09:24 +00:00
{
static bool old_should_slot_increase = false ;
static bool old_should_slot_decrease = false ;
2017-12-05 11:07:35 +00:00
bool should_slot_increase = BIT256_GET (
2017-05-21 10:09:24 +00:00
current_input , RARCH_STATE_SLOT_PLUS ) ;
2017-12-05 11:07:35 +00:00
bool should_slot_decrease = BIT256_GET (
2017-05-21 10:09:24 +00:00
current_input , RARCH_STATE_SLOT_MINUS ) ;
2018-09-27 12:02:11 +00:00
bool should_set = false ;
2019-01-14 04:25:04 +00:00
int cur_state_slot = settings - > ints . state_slot ;
2017-05-21 10:09:24 +00:00
2017-07-05 01:46:22 +00:00
/* Checks if the state increase/decrease keys have been pressed
2017-05-21 10:09:24 +00:00
* for this frame . */
if ( should_slot_increase & & ! old_should_slot_increase )
{
2019-01-14 04:25:04 +00:00
configuration_set_int ( settings , settings - > ints . state_slot , cur_state_slot + 1 ) ;
2017-05-21 10:09:24 +00:00
2018-09-27 12:02:11 +00:00
should_set = true ;
2017-05-21 10:09:24 +00:00
}
else if ( should_slot_decrease & & ! old_should_slot_decrease )
{
2019-01-12 16:58:35 +00:00
if ( cur_state_slot > 0 )
2019-01-14 04:25:04 +00:00
configuration_set_int ( settings , settings - > ints . state_slot , cur_state_slot - 1 ) ;
2018-09-27 12:02:11 +00:00
should_set = true ;
}
if ( should_set )
{
char msg [ 128 ] ;
msg [ 0 ] = ' \0 ' ;
2017-05-21 10:09:24 +00:00
snprintf ( msg , sizeof ( msg ) , " %s: %d " ,
msg_hash_to_str ( MSG_STATE_SLOT ) ,
settings - > ints . state_slot ) ;
2018-11-22 14:45:52 +00:00
runloop_msg_queue_push ( msg , 2 , 180 , true , NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_INFO ) ;
2017-05-21 10:09:24 +00:00
RARCH_LOG ( " %s \n " , msg ) ;
}
old_should_slot_increase = should_slot_increase ;
old_should_slot_decrease = should_slot_decrease ;
}
2019-02-28 20:54:46 +00:00
/* Check if we have pressed any of the savestate buttons */
2017-05-21 10:09:24 +00:00
{
static bool old_should_savestate = false ;
static bool old_should_loadstate = false ;
2017-12-05 11:07:35 +00:00
bool should_savestate = BIT256_GET (
2017-05-21 10:09:24 +00:00
current_input , RARCH_SAVE_STATE_KEY ) ;
2017-12-05 11:07:35 +00:00
bool should_loadstate = BIT256_GET (
2017-05-21 10:09:24 +00:00
current_input , RARCH_LOAD_STATE_KEY ) ;
if ( should_savestate & & ! old_should_savestate )
command_event ( CMD_EVENT_SAVE_STATE , NULL ) ;
if ( should_loadstate & & ! old_should_loadstate )
command_event ( CMD_EVENT_LOAD_STATE , NULL ) ;
old_should_savestate = should_savestate ;
old_should_loadstate = should_loadstate ;
}
2017-05-11 07:11:46 +00:00
2018-05-13 23:44:08 +00:00
# ifdef HAVE_CHEEVOS
2018-04-30 19:39:20 +00:00
cheevos_hardcore_active = settings - > bools . cheevos_enable
2019-01-14 04:25:04 +00:00
& & settings - > bools . cheevos_hardcore_mode_enable
& & cheevos_loaded & & ! cheevos_hardcore_paused ;
2018-04-30 19:39:20 +00:00
2018-09-21 04:20:38 +00:00
if ( cheevos_hardcore_active & & cheevos_state_loaded_flag )
{
cheevos_hardcore_paused = true ;
2018-11-22 14:45:52 +00:00
runloop_msg_queue_push ( msg_hash_to_str ( MSG_CHEEVOS_HARDCORE_MODE_DISABLED ) , 0 , 180 , true , NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_INFO ) ;
2018-09-21 04:20:38 +00:00
}
2018-04-30 19:39:20 +00:00
if ( ! cheevos_hardcore_active )
2017-05-11 07:11:46 +00:00
# endif
{
char s [ 128 ] ;
unsigned t = 0 ;
s [ 0 ] = ' \0 ' ;
2019-02-08 06:26:43 +00:00
if ( state_manager_check_rewind ( BIT256_GET ( current_input , RARCH_REWIND ) ,
settings - > uints . rewind_granularity , runloop_is_paused , s , sizeof ( s ) , & t ) )
runloop_msg_queue_push ( s , 0 , t , true , NULL ,
MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_INFO ) ;
2017-05-11 07:11:46 +00:00
}
2017-05-21 11:06:48 +00:00
/* Checks if slowmotion toggle/hold was being pressed and/or held. */
2018-04-30 15:27:35 +00:00
# ifdef HAVE_CHEEVOS
2018-04-30 19:39:20 +00:00
if ( ! cheevos_hardcore_active )
2018-04-30 15:27:35 +00:00
# endif
2017-05-11 07:11:46 +00:00
{
2018-03-10 17:42:45 +00:00
static bool old_slowmotion_button_state = false ;
static bool old_slowmotion_hold_button_state = false ;
bool new_slowmotion_button_state = BIT256_GET (
current_input , RARCH_SLOWMOTION_KEY ) ;
bool new_slowmotion_hold_button_state = BIT256_GET (
current_input , RARCH_SLOWMOTION_HOLD_KEY ) ;
if ( new_slowmotion_button_state & & ! old_slowmotion_button_state )
2019-01-12 16:58:35 +00:00
{
if ( runloop_slowmotion )
runloop_slowmotion = false ;
else
runloop_slowmotion = true ;
}
2018-03-10 17:42:45 +00:00
else if ( old_slowmotion_hold_button_state ! = new_slowmotion_hold_button_state )
{
2018-04-10 05:19:27 +00:00
if ( new_slowmotion_hold_button_state )
2018-03-10 17:42:45 +00:00
runloop_slowmotion = true ;
2018-04-10 05:19:27 +00:00
else
2018-03-10 17:42:45 +00:00
runloop_slowmotion = false ;
}
2017-05-21 11:06:48 +00:00
if ( runloop_slowmotion )
2017-05-11 07:11:46 +00:00
{
2017-05-21 11:06:48 +00:00
if ( settings - > bools . video_black_frame_insertion )
if ( ! runloop_idle )
video_driver_cached_frame ( ) ;
2017-05-11 07:11:46 +00:00
2019-02-08 06:26:43 +00:00
if ( state_manager_frame_is_reversed ( ) )
runloop_msg_queue_push (
msg_hash_to_str ( MSG_SLOW_MOTION_REWIND ) , 1 , 1 , false , NULL ,
MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_INFO ) ;
else
runloop_msg_queue_push (
msg_hash_to_str ( MSG_SLOW_MOTION ) , 1 , 1 , false ,
NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_INFO ) ;
2017-05-21 11:06:48 +00:00
}
2018-03-10 17:42:45 +00:00
old_slowmotion_button_state = new_slowmotion_button_state ;
old_slowmotion_hold_button_state = new_slowmotion_hold_button_state ;
2017-05-11 07:11:46 +00:00
}
2017-05-21 11:06:48 +00:00
/* Check movie record toggle */
{
static bool old_pressed = false ;
2017-12-05 11:07:35 +00:00
bool pressed = BIT256_GET (
2018-09-16 02:26:37 +00:00
current_input , RARCH_BSV_RECORD_TOGGLE ) ;
2017-05-21 11:06:48 +00:00
if ( pressed & & ! old_pressed )
2018-09-15 22:44:46 +00:00
{
2018-09-16 02:09:41 +00:00
if ( ! recording_is_enabled ( ) )
command_event ( CMD_EVENT_RECORD_INIT , NULL ) ;
else
command_event ( CMD_EVENT_RECORD_DEINIT , NULL ) ;
2017-05-21 11:06:48 +00:00
bsv_movie_check ( ) ;
2018-09-15 22:44:46 +00:00
}
2017-05-21 11:06:48 +00:00
old_pressed = pressed ;
}
2017-05-11 07:11:46 +00:00
2017-05-21 11:26:25 +00:00
/* Check shader prev/next */
{
static bool old_shader_next = false ;
static bool old_shader_prev = false ;
2017-12-05 11:07:35 +00:00
bool shader_next = BIT256_GET (
2017-05-21 11:26:25 +00:00
current_input , RARCH_SHADER_NEXT ) ;
2017-12-05 11:07:35 +00:00
bool shader_prev = BIT256_GET (
2017-05-21 11:26:25 +00:00
current_input , RARCH_SHADER_PREV ) ;
bool trig_shader_next = shader_next & & ! old_shader_next ;
bool trig_shader_prev = shader_prev & & ! old_shader_prev ;
if ( trig_shader_next | | trig_shader_prev )
dir_check_shader ( trig_shader_next , trig_shader_prev ) ;
old_shader_next = shader_next ;
old_shader_prev = shader_prev ;
}
2017-05-11 07:11:46 +00:00
2019-02-28 20:54:46 +00:00
/* Check if we have pressed any of the disk buttons */
2017-05-21 11:39:29 +00:00
{
static bool old_disk_eject = false ;
static bool old_disk_next = false ;
static bool old_disk_prev = false ;
2017-12-05 11:07:35 +00:00
bool disk_eject = BIT256_GET (
2017-05-21 11:39:29 +00:00
current_input , RARCH_DISK_EJECT_TOGGLE ) ;
2017-12-05 11:07:35 +00:00
bool disk_next = BIT256_GET (
2017-05-21 11:39:29 +00:00
current_input , RARCH_DISK_NEXT ) ;
2017-12-05 11:07:35 +00:00
bool disk_prev = BIT256_GET (
2017-05-21 11:39:29 +00:00
current_input , RARCH_DISK_PREV ) ;
if ( disk_eject & & ! old_disk_eject )
command_event ( CMD_EVENT_DISK_EJECT_TOGGLE , NULL ) ;
else if ( disk_next & & ! old_disk_next )
command_event ( CMD_EVENT_DISK_NEXT , NULL ) ;
else if ( disk_prev & & ! old_disk_prev )
command_event ( CMD_EVENT_DISK_PREV , NULL ) ;
old_disk_eject = disk_eject ;
old_disk_prev = disk_prev ;
old_disk_next = disk_next ;
}
2017-05-11 07:11:46 +00:00
2019-02-28 20:54:46 +00:00
/* Check if we have pressed the reset button */
2017-05-21 10:09:24 +00:00
{
static bool old_state = false ;
2017-12-05 11:07:35 +00:00
bool new_state = BIT256_GET (
2017-05-21 10:09:24 +00:00
current_input , RARCH_RESET ) ;
if ( new_state & & ! old_state )
command_event ( CMD_EVENT_RESET , NULL ) ;
old_state = new_state ;
}
2017-05-11 07:11:46 +00:00
2017-05-21 11:17:48 +00:00
/* Check cheats */
{
static bool old_cheat_index_plus = false ;
static bool old_cheat_index_minus = false ;
static bool old_cheat_index_toggle = false ;
2017-12-05 11:07:35 +00:00
bool cheat_index_plus = BIT256_GET (
2017-05-21 11:17:48 +00:00
current_input , RARCH_CHEAT_INDEX_PLUS ) ;
2017-12-05 11:07:35 +00:00
bool cheat_index_minus = BIT256_GET (
2017-05-21 11:17:48 +00:00
current_input , RARCH_CHEAT_INDEX_MINUS ) ;
2017-12-05 11:07:35 +00:00
bool cheat_index_toggle = BIT256_GET (
2017-05-21 11:17:48 +00:00
current_input , RARCH_CHEAT_TOGGLE ) ;
if ( cheat_index_plus & & ! old_cheat_index_plus )
cheat_manager_index_next ( ) ;
else if ( cheat_index_minus & & ! old_cheat_index_minus )
cheat_manager_index_prev ( ) ;
else if ( cheat_index_toggle & & ! old_cheat_index_toggle )
cheat_manager_toggle ( ) ;
old_cheat_index_plus = cheat_index_plus ;
old_cheat_index_minus = cheat_index_minus ;
old_cheat_index_toggle = cheat_index_toggle ;
}
2017-05-11 07:11:46 +00:00
2018-01-25 20:50:57 +00:00
if ( settings - > bools . video_shader_watch_files )
{
2018-01-27 01:27:29 +00:00
static rarch_timer_t timer = { 0 } ;
2018-01-26 00:09:55 +00:00
static bool need_to_apply = false ;
2018-01-25 20:50:57 +00:00
if ( video_shader_check_for_changes ( ) )
2018-01-26 00:09:55 +00:00
{
need_to_apply = true ;
2018-01-27 01:27:29 +00:00
if ( ! rarch_timer_is_running ( & timer ) )
{
/* rarch_timer_t convenience functions only support whole seconds. */
/* rarch_timer_begin */
timer . timeout_end = cpu_features_get_time_usec ( ) + SHADER_FILE_WATCH_DELAY_MSEC * 1000 ;
timer . timer_begin = true ;
2018-09-27 12:02:11 +00:00
timer . timer_end = false ;
2018-01-27 01:27:29 +00:00
}
2018-01-26 00:09:55 +00:00
}
/* If a file is modified atomically (moved/renamed from a different file), we have no idea how long that might take.
* If we ' re trying to re - apply shaders immediately after changes are made to the original file ( s ) , the filesystem might be in an in - between
* state where the new file hasn ' t been moved over yet and the original file was already deleted . This leaves us no choice
* but to wait an arbitrary amount of time and hope for the best .
*/
if ( need_to_apply )
{
2018-01-27 01:27:29 +00:00
/* rarch_timer_tick */
2018-09-27 12:02:11 +00:00
timer . current = cpu_features_get_time_usec ( ) ;
2018-04-04 08:37:16 +00:00
timer . timeout_us = ( timer . timeout_end - timer . current ) ;
2018-01-27 01:27:29 +00:00
if ( ! timer . timer_end & & rarch_timer_has_expired ( & timer ) )
2018-01-26 00:09:55 +00:00
{
2018-01-27 01:27:29 +00:00
rarch_timer_end ( & timer ) ;
2018-01-26 00:09:55 +00:00
need_to_apply = false ;
command_event ( CMD_EVENT_SHADERS_APPLY_CHANGES , NULL ) ;
}
}
2018-01-25 20:50:57 +00:00
}
2017-05-11 07:11:46 +00:00
return RUNLOOP_STATE_ITERATE ;
2019-01-14 04:25:04 +00:00
quit :
old_quit_key = quit_key ;
retroarch_main_quit ( ) ;
return RUNLOOP_STATE_QUIT ;
2017-05-11 07:11:46 +00:00
}
void runloop_set ( enum runloop_action action )
{
switch ( action )
{
case RUNLOOP_ACTION_AUTOSAVE :
runloop_autosave = true ;
break ;
case RUNLOOP_ACTION_NONE :
break ;
}
}
void runloop_unset ( enum runloop_action action )
{
switch ( action )
{
case RUNLOOP_ACTION_AUTOSAVE :
runloop_autosave = false ;
break ;
case RUNLOOP_ACTION_NONE :
break ;
}
}
/**
* runloop_iterate :
*
* Run Libretro core in RetroArch for one frame .
*
* Returns : 0 on success , 1 if we have to wait until
* button input in order to wake up the loop ,
* - 1 if we forcibly quit out of the RetroArch iteration loop .
* */
int runloop_iterate ( unsigned * sleep_ms )
{
unsigned i ;
2019-01-12 16:58:35 +00:00
bool runloop_is_paused = runloop_paused ;
2017-05-21 19:55:20 +00:00
bool input_nonblock_state = input_driver_is_nonblock_state ( ) ;
2017-05-11 07:11:46 +00:00
settings_t * settings = config_get_ptr ( ) ;
2019-01-12 16:58:35 +00:00
float fastforward_ratio = settings - > floats . fastforward_ratio ;
unsigned video_frame_delay = settings - > uints . video_frame_delay ;
bool vrr_runloop_enable = settings - > bools . vrr_runloop_enable ;
2017-05-11 07:11:46 +00:00
unsigned max_users = * ( input_driver_get_uint ( INPUT_ACTION_MAX_USERS ) ) ;
2017-05-20 20:55:12 +00:00
2018-09-09 21:41:50 +00:00
# ifdef HAVE_DISCORD
2018-09-15 05:17:29 +00:00
if ( discord_is_inited )
2018-09-09 21:41:50 +00:00
discord_run_callbacks ( ) ;
# endif
2017-05-11 07:11:46 +00:00
if ( runloop_frame_time . callback )
{
/* Updates frame timing if frame timing callback is in use by the core.
* Limits frame time if fast forward ratio throttle is enabled . */
2019-01-12 16:58:35 +00:00
retro_usec_t runloop_last_frame_time = runloop_frame_time_last ;
retro_time_t current = cpu_features_get_time_usec ( ) ;
bool is_locked_fps = ( runloop_is_paused | | input_nonblock_state )
| ! ! recording_data ;
retro_time_t delta = ( ! runloop_last_frame_time | | is_locked_fps ) ?
runloop_frame_time . reference
: ( current - runloop_last_frame_time ) ;
2017-05-11 07:11:46 +00:00
if ( is_locked_fps )
runloop_frame_time_last = 0 ;
2019-01-12 16:58:35 +00:00
else
{
float slowmotion_ratio = settings - > floats . slowmotion_ratio ;
runloop_frame_time_last = current ;
if ( runloop_slowmotion )
delta / = slowmotion_ratio ;
}
2017-05-11 07:11:46 +00:00
runloop_frame_time . callback ( delta ) ;
}
switch ( ( enum runloop_state )
runloop_check_state (
settings ,
2017-05-21 19:55:20 +00:00
input_nonblock_state ,
2019-01-12 16:58:35 +00:00
runloop_is_paused ,
fastforward_ratio ,
2017-05-11 07:11:46 +00:00
sleep_ms ) )
{
case RUNLOOP_STATE_QUIT :
frame_limit_last_time = 0.0 ;
command_event ( CMD_EVENT_QUIT , NULL ) ;
return - 1 ;
2017-05-29 18:30:01 +00:00
case RUNLOOP_STATE_POLLED_AND_SLEEP :
runloop_netplay_pause ( ) ;
* sleep_ms = 10 ;
return 1 ;
2017-05-11 07:11:46 +00:00
case RUNLOOP_STATE_SLEEP :
2017-05-29 18:30:01 +00:00
retro_ctx . poll_cb ( ) ;
2017-05-11 07:11:46 +00:00
runloop_netplay_pause ( ) ;
* sleep_ms = 10 ;
return 1 ;
case RUNLOOP_STATE_END :
runloop_netplay_pause ( ) ;
goto end ;
case RUNLOOP_STATE_MENU_ITERATE :
runloop_netplay_pause ( ) ;
return 0 ;
case RUNLOOP_STATE_ITERATE :
break ;
}
if ( runloop_autosave )
autosave_lock ( ) ;
2019-01-13 06:46:35 +00:00
/* Used for rewinding while playback/record. */
if ( bsv_movie_state_handle )
bsv_movie_state_handle - > frame_pos [ bsv_movie_state_handle - > frame_ptr ]
= intfstream_tell ( bsv_movie_state_handle - > file ) ;
2017-05-11 07:11:46 +00:00
camera_driver_poll ( ) ;
/* Update binds for analog dpad modes. */
for ( i = 0 ; i < max_users ; i + + )
{
struct retro_keybind * general_binds = input_config_binds [ i ] ;
struct retro_keybind * auto_binds = input_autoconf_binds [ i ] ;
enum analog_dpad_mode dpad_mode = ( enum analog_dpad_mode ) settings - > uints . input_analog_dpad_mode [ i ] ;
if ( dpad_mode = = ANALOG_DPAD_NONE )
continue ;
input_push_analog_dpad ( general_binds , dpad_mode ) ;
input_push_analog_dpad ( auto_binds , dpad_mode ) ;
}
2019-01-12 16:58:35 +00:00
if ( ( video_frame_delay > 0 ) & & ! input_nonblock_state )
retro_sleep ( video_frame_delay ) ;
2017-05-11 07:11:46 +00:00
2018-03-29 13:38:22 +00:00
# ifdef HAVE_RUNAHEAD
2019-01-12 16:58:35 +00:00
{
unsigned run_ahead_num_frames = settings - > uints . run_ahead_frames ;
/* Run Ahead Feature replaces the call to core_run in this loop */
if ( settings - > bools . run_ahead_enabled & & run_ahead_num_frames > 0
2018-05-31 02:01:02 +00:00
# ifdef HAVE_NETWORKING
2019-01-12 16:58:35 +00:00
& & ! netplay_driver_ctl ( RARCH_NETPLAY_CTL_IS_ENABLED , NULL )
2018-05-31 02:01:02 +00:00
# endif
2019-01-12 16:58:35 +00:00
)
run_ahead ( run_ahead_num_frames , settings - > bools . run_ahead_secondary_instance ) ;
else
2019-02-12 05:32:01 +00:00
{
2019-01-12 16:58:35 +00:00
core_run ( ) ;
2019-02-12 05:32:01 +00:00
}
2019-01-12 16:58:35 +00:00
}
# else
2019-02-12 05:32:01 +00:00
{
core_run ( ) ;
}
2018-03-29 13:38:22 +00:00
# endif
2017-05-11 07:11:46 +00:00
2019-03-04 11:33:19 +00:00
/* Increment runtime tick counter after each call to
* core_run ( ) or run_ahead ( ) */
rarch_core_runtime_tick ( ) ;
2017-05-11 07:11:46 +00:00
# ifdef HAVE_CHEEVOS
if ( runloop_check_cheevos ( ) )
cheevos_test ( ) ;
# endif
2019-01-12 16:58:35 +00:00
cheat_manager_apply_retro_cheats ( ) ;
2018-07-25 23:19:14 +00:00
2018-05-29 04:43:30 +00:00
# ifdef HAVE_DISCORD
2018-05-29 09:06:43 +00:00
if ( discord_is_inited )
2018-05-29 10:41:13 +00:00
{
discord_userdata_t userdata ;
userdata . status = DISCORD_PRESENCE_GAME ;
command_event ( CMD_EVENT_DISCORD_UPDATE , & userdata ) ;
}
2018-05-29 04:43:30 +00:00
# endif
2017-05-11 07:11:46 +00:00
for ( i = 0 ; i < max_users ; i + + )
{
struct retro_keybind * general_binds = input_config_binds [ i ] ;
struct retro_keybind * auto_binds = input_autoconf_binds [ i ] ;
enum analog_dpad_mode dpad_mode = ( enum analog_dpad_mode ) settings - > uints . input_analog_dpad_mode [ i ] ;
if ( dpad_mode = = ANALOG_DPAD_NONE )
continue ;
input_pop_analog_dpad ( general_binds ) ;
input_pop_analog_dpad ( auto_binds ) ;
}
2019-01-13 06:46:35 +00:00
if ( bsv_movie_state_handle )
{
bsv_movie_state_handle - > frame_ptr =
( bsv_movie_state_handle - > frame_ptr + 1 )
& bsv_movie_state_handle - > frame_mask ;
bsv_movie_state_handle - > first_rewind =
! bsv_movie_state_handle - > did_rewind ;
bsv_movie_state_handle - > did_rewind = false ;
}
2017-05-11 07:11:46 +00:00
if ( runloop_autosave )
autosave_unlock ( ) ;
2018-08-04 22:34:10 +00:00
/* Condition for max speed x0.0 when vrr_runloop is off to skip that part */
2019-01-12 16:58:35 +00:00
if ( fastforward_ratio | | vrr_runloop_enable )
2017-05-21 20:43:40 +00:00
end :
{
2018-08-10 22:15:32 +00:00
retro_time_t to_sleep_ms ;
2018-08-19 03:09:40 +00:00
2019-01-12 16:58:35 +00:00
if ( vrr_runloop_enable )
2018-08-04 22:34:10 +00:00
{
struct retro_system_av_info * av_info =
video_viewport_get_system_av_info ( ) ;
/* Sync on video only, block audio later. */
if ( fastforward_after_frames & & settings - > bools . audio_sync )
{
if ( fastforward_after_frames = = 1 )
command_event ( CMD_EVENT_AUDIO_SET_NONBLOCKING_STATE , NULL ) ;
fastforward_after_frames + + ;
if ( fastforward_after_frames = = 6 )
{
command_event ( CMD_EVENT_AUDIO_SET_BLOCKING_STATE , NULL ) ;
fastforward_after_frames = 0 ;
}
}
/* Fast Forward for max speed x0.0 */
2019-01-12 16:58:35 +00:00
if ( ! fastforward_ratio & & runloop_fastmotion )
2018-08-04 22:34:10 +00:00
return 0 ;
2018-08-19 03:09:40 +00:00
frame_limit_minimum_time =
2018-08-04 22:34:10 +00:00
( retro_time_t ) roundf ( 1000000.0f / ( av_info - > timing . fps *
2019-01-12 16:58:35 +00:00
( runloop_fastmotion ? fastforward_ratio : 1.0f ) ) ) ;
2018-08-04 22:34:10 +00:00
}
2018-08-10 22:15:32 +00:00
to_sleep_ms = (
2017-05-21 20:43:40 +00:00
( frame_limit_last_time + frame_limit_minimum_time )
- cpu_features_get_time_usec ( ) ) / 1000 ;
2017-05-11 07:11:46 +00:00
2017-05-21 20:43:40 +00:00
if ( to_sleep_ms > 0 )
{
2019-01-12 16:58:35 +00:00
* sleep_ms = ( unsigned ) to_sleep_ms ;
2017-05-21 20:43:40 +00:00
/* Combat jitter a bit. */
frame_limit_last_time + = frame_limit_minimum_time ;
return 1 ;
}
2017-05-11 07:11:46 +00:00
2017-05-21 20:43:40 +00:00
frame_limit_last_time = cpu_features_get_time_usec ( ) ;
2017-05-11 07:11:46 +00:00
}
return 0 ;
}
rarch_system_info_t * runloop_get_system_info ( void )
{
return & runloop_system ;
}
2018-10-30 07:21:32 +00:00
struct retro_system_info * runloop_get_libretro_system_info ( void )
{
struct retro_system_info * system = & runloop_system . info ;
return system ;
}
2019-01-05 20:11:58 +00:00
char * get_retroarch_launch_arguments ( void )
{
return launch_arguments ;
2019-01-06 16:04:28 +00:00
}
2019-01-31 14:48:10 +00:00
void rarch_force_video_driver_fallback ( const char * driver )
{
settings_t * settings = config_get_ptr ( ) ;
ui_msg_window_t * msg_window = NULL ;
2019-03-11 15:58:43 +00:00
strlcpy ( settings - > arrays . video_driver ,
driver , sizeof ( settings - > arrays . video_driver ) ) ;
2019-01-31 14:48:10 +00:00
command_event ( CMD_EVENT_MENU_SAVE_CURRENT_CONFIG , NULL ) ;
2019-02-04 22:13:56 +00:00
# if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__) && !defined(WINAPI_FAMILY)
2019-01-31 14:48:10 +00:00
/* UI companion driver is not inited yet, just call into it directly */
msg_window = & ui_msg_window_win32 ;
# endif
if ( msg_window )
{
char text [ PATH_MAX_LENGTH ] ;
2019-03-11 15:58:43 +00:00
ui_msg_window_state window_state ;
char * title = strdup ( msg_hash_to_str ( MSG_ERROR ) ) ;
2019-01-31 14:48:10 +00:00
2019-01-31 19:12:41 +00:00
text [ 0 ] = ' \0 ' ;
2019-01-31 14:48:10 +00:00
2019-01-31 19:12:41 +00:00
snprintf ( text , sizeof ( text ) ,
msg_hash_to_str ( MENU_ENUM_LABEL_VALUE_VIDEO_DRIVER_FALLBACK ) ,
driver ) ;
2019-01-31 14:48:10 +00:00
window_state . buttons = UI_MSG_WINDOW_OK ;
2019-01-31 19:12:41 +00:00
window_state . text = strdup ( text ) ;
window_state . title = title ;
window_state . window = NULL ;
2019-01-31 14:48:10 +00:00
msg_window - > error ( & window_state ) ;
free ( title ) ;
}
exit ( 1 ) ;
}
2019-03-08 00:17:54 +00:00
void rarch_get_cpu_architecture_string ( char * cpu_arch_str , size_t len )
{
enum frontend_architecture arch = frontend_driver_get_cpu_architecture ( ) ;
if ( ! cpu_arch_str | | ! len )
return ;
switch ( arch )
{
case FRONTEND_ARCH_X86 :
strlcpy ( cpu_arch_str , " x86 " , len ) ;
break ;
case FRONTEND_ARCH_X86_64 :
strlcpy ( cpu_arch_str , " x64 " , len ) ;
break ;
case FRONTEND_ARCH_PPC :
strlcpy ( cpu_arch_str , " PPC " , len ) ;
break ;
case FRONTEND_ARCH_ARM :
strlcpy ( cpu_arch_str , " ARM " , len ) ;
break ;
case FRONTEND_ARCH_ARMV7 :
strlcpy ( cpu_arch_str , " ARMv7 " , len ) ;
break ;
case FRONTEND_ARCH_ARMV8 :
strlcpy ( cpu_arch_str , " ARMv8 " , len ) ;
break ;
case FRONTEND_ARCH_MIPS :
strlcpy ( cpu_arch_str , " MIPS " , len ) ;
break ;
case FRONTEND_ARCH_TILE :
strlcpy ( cpu_arch_str , " Tilera " , len ) ;
break ;
case FRONTEND_ARCH_NONE :
default :
strlcpy ( cpu_arch_str ,
msg_hash_to_str ( MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE ) ,
len ) ;
break ;
}
}
bool rarch_write_debug_info ( void )
{
2019-03-11 15:58:43 +00:00
int i ;
2019-03-08 00:17:54 +00:00
gfx_ctx_mode_t mode_info = { 0 } ;
char str [ PATH_MAX_LENGTH ] ;
char debug_filepath [ PATH_MAX_LENGTH ] ;
2019-03-11 15:58:43 +00:00
settings_t * settings = config_get_ptr ( ) ;
RFILE * file = NULL ;
2019-03-08 00:17:54 +00:00
const frontend_ctx_driver_t * frontend = frontend_get_ptr ( ) ;
2019-03-11 15:58:43 +00:00
const char * cpu_model = NULL ;
const char * path_config = path_get ( RARCH_PATH_CONFIG ) ;
unsigned lang =
* msg_hash_get_uint ( MSG_HASH_USER_LANGUAGE ) ;
2019-03-08 00:17:54 +00:00
str [ 0 ] = debug_filepath [ 0 ] = ' \0 ' ;
2019-03-11 15:58:43 +00:00
/* Only print our debug info in English */
2019-03-08 00:17:54 +00:00
if ( lang ! = RETRO_LANGUAGE_ENGLISH )
msg_hash_set_uint ( MSG_HASH_USER_LANGUAGE , RETRO_LANGUAGE_ENGLISH ) ;
fill_pathname_resolve_relative (
debug_filepath ,
path_config ,
DEBUG_INFO_FILENAME ,
sizeof ( debug_filepath ) ) ;
2019-03-11 15:58:43 +00:00
file = filestream_open ( debug_filepath ,
RETRO_VFS_FILE_ACCESS_WRITE , RETRO_VFS_FILE_ACCESS_HINT_NONE ) ;
2019-03-08 00:17:54 +00:00
if ( ! file )
{
RARCH_ERR ( " Could not open debug info file for writing: %s \n " , debug_filepath ) ;
goto error ;
}
# ifdef HAVE_MENU
{
time_t time_ ;
char timedate [ 255 ] ;
timedate [ 0 ] = ' \0 ' ;
time ( & time_ ) ;
setlocale ( LC_TIME , " " ) ;
strftime ( timedate , sizeof ( timedate ) ,
" %Y-%m-%d %H:%M:%S " , localtime ( & time_ ) ) ;
filestream_printf ( file , " Log Date/Time: %s \n " , timedate ) ;
}
# endif
filestream_printf ( file , " RetroArch Version: %s \n " , PACKAGE_VERSION ) ;
# ifdef HAVE_LAKKA
if ( frontend - > get_lakka_version )
{
frontend - > get_lakka_version ( str , sizeof ( str ) ) ;
filestream_printf ( file , " Lakka Version: %s \n " , str ) ;
str [ 0 ] = ' \0 ' ;
}
# endif
filestream_printf ( file , " RetroArch Build Date: %s \n " , __DATE__ ) ;
# ifdef HAVE_GIT_VERSION
filestream_printf ( file , " RetroArch Git Commit: %s \n " , retroarch_git_version ) ;
# endif
filestream_printf ( file , " \n " ) ;
cpu_model = frontend_driver_get_cpu_model_name ( ) ;
if ( ! string_is_empty ( cpu_model ) )
filestream_printf ( file , " CPU Model Name: %s \n " , cpu_model ) ;
retroarch_get_capabilities ( RARCH_CAPABILITIES_CPU , str , sizeof ( str ) ) ;
filestream_printf ( file , " CPU Capabilities: %s \n " , str ) ;
str [ 0 ] = ' \0 ' ;
rarch_get_cpu_architecture_string ( str , sizeof ( str ) ) ;
filestream_printf ( file , " CPU Architecture: %s \n " , str ) ;
filestream_printf ( file , " CPU Cores: %u \n " , cpu_features_get_core_amount ( ) ) ;
{
uint64_t memory_used = frontend_driver_get_used_memory ( ) ;
uint64_t memory_total = frontend_driver_get_total_memory ( ) ;
filestream_printf ( file , " Memory: % " PRIu64 " /% " PRIu64 " MB \n " , memory_used / 1024 / 1024 , memory_total / 1024 / 1024 ) ;
}
filestream_printf ( file , " GPU Device: %s \n " , ! string_is_empty ( video_driver_get_gpu_device_string ( ) ) ?
video_driver_get_gpu_device_string ( ) : " n/a " ) ;
filestream_printf ( file , " GPU API/Driver Version: %s \n " , ! string_is_empty ( video_driver_get_gpu_api_version_string ( ) ) ?
video_driver_get_gpu_api_version_string ( ) : " n/a " ) ;
filestream_printf ( file , " \n " ) ;
video_context_driver_get_video_size ( & mode_info ) ;
filestream_printf ( file , " Window Resolution: %u x %u \n " , mode_info . width , mode_info . height ) ;
{
float width = 0 , height = 0 , refresh = 0.0f ;
2019-03-13 16:00:52 +00:00
gfx_ctx_metrics_t metrics ;
metrics . type = DISPLAY_METRIC_PIXEL_WIDTH ;
2019-03-08 00:17:54 +00:00
metrics . value = & width ;
2019-03-13 16:00:52 +00:00
2019-03-08 00:17:54 +00:00
video_context_driver_get_metrics ( & metrics ) ;
metrics . type = DISPLAY_METRIC_PIXEL_HEIGHT ;
metrics . value = & height ;
video_context_driver_get_metrics ( & metrics ) ;
video_context_driver_get_refresh_rate ( & refresh ) ;
filestream_printf ( file , " Monitor Resolution: %d x %d @ %.2f Hz (configured for %.2f Hz) \n " , ( int ) width , ( int ) height , refresh , settings - > floats . video_refresh_rate ) ;
}
filestream_printf ( file , " \n " ) ;
str [ 0 ] = ' \0 ' ;
retroarch_get_capabilities ( RARCH_CAPABILITIES_COMPILER , str , sizeof ( str ) ) ;
filestream_printf ( file , " %s \n " , str ) ;
str [ 0 ] = ' \0 ' ;
filestream_printf ( file , " Frontend Identifier: %s \n " , frontend - > ident ) ;
if ( frontend - > get_name )
{
frontend - > get_name ( str , sizeof ( str ) ) ;
filestream_printf ( file , " Frontend Name: %s \n " , str ) ;
str [ 0 ] = ' \0 ' ;
}
if ( frontend - > get_os )
{
int major = 0 , minor = 0 ;
const char * warning = " " ;
frontend - > get_os ( str , sizeof ( str ) , & major , & minor ) ;
if ( strstr ( str , " Build 16299 " ) )
warning = " (WARNING: Fall Creator's Update detected... OpenGL performance may be low) " ;
filestream_printf ( file , " Frontend OS: %s (v%d.%d)%s \n " , str , major , minor , warning ) ;
str [ 0 ] = ' \0 ' ;
}
filestream_printf ( file , " \n " ) ;
filestream_printf ( file , " Input Devices (autoconfig is %s): \n " , settings - > bools . input_autodetect_enable ? " enabled " : " disabled " ) ;
for ( i = 0 ; i < 4 ; i + + )
{
if ( input_is_autoconfigured ( i ) )
{
unsigned rebind = 0 ;
unsigned retro_id ;
unsigned device = settings - > uints . input_libretro_device [ i ] ;
device & = RETRO_DEVICE_MASK ;
if ( device = = RETRO_DEVICE_JOYPAD | | device = = RETRO_DEVICE_ANALOG )
{
for ( retro_id = 0 ; retro_id < RARCH_ANALOG_BIND_LIST_END ; retro_id + + )
{
char descriptor [ 300 ] ;
const struct retro_keybind * auto_bind = NULL ;
const struct retro_keybind * keybind = NULL ;
keybind = & input_config_binds [ i ] [ retro_id ] ;
auto_bind = ( const struct retro_keybind * )
input_config_get_bind_auto ( i , retro_id ) ;
input_config_get_bind_string ( descriptor ,
keybind , auto_bind , sizeof ( descriptor ) ) ;
if ( ! strstr ( descriptor , " Auto " ) & & auto_bind & & ! auto_bind - > valid & & auto_bind - > joykey ! = 0xFFFF & & ! string_is_empty ( auto_bind - > joykey_label ) )
rebind + + ;
}
}
if ( rebind )
filestream_printf ( file , " - Port #%d autoconfigured (WARNING: %u keys rebinded): \n " , i , rebind ) ;
else
filestream_printf ( file , " - Port #%d autoconfigured: \n " , i ) ;
filestream_printf ( file , " - Device name: %s (#%d) \n " ,
input_config_get_device_name ( i ) ,
input_autoconfigure_get_device_name_index ( i ) ) ;
filestream_printf ( file , " - Display name: %s \n " ,
input_config_get_device_display_name ( i ) ?
input_config_get_device_display_name ( i ) : " N/A " ) ;
filestream_printf ( file , " - Config path: %s \n " ,
input_config_get_device_display_name ( i ) ?
input_config_get_device_config_path ( i ) : " N/A " ) ;
filestream_printf ( file , " - VID/PID: %d/%d (0x%04X/0x%04X) \n " ,
input_config_get_vid ( i ) , input_config_get_pid ( i ) ,
input_config_get_vid ( i ) , input_config_get_pid ( i ) ) ;
}
else
filestream_printf ( file , " - Port #%d not autoconfigured \n " , i ) ;
}
filestream_printf ( file , " \n " ) ;
filestream_printf ( file , " Drivers: \n " ) ;
{
gfx_ctx_ident_t ident_info = { 0 } ;
const input_driver_t * input_driver ;
const input_device_driver_t * joypad_driver ;
const char * driver = menu_driver_ident ( ) ;
if ( string_is_equal ( driver , settings - > arrays . menu_driver ) )
filestream_printf ( file , " - Menu: %s \n " , ! string_is_empty ( driver ) ? driver : " n/a " ) ;
else
filestream_printf ( file , " - Menu: %s (configured for %s) \n " , ! string_is_empty ( driver ) ? driver : " n/a " , ! string_is_empty ( settings - > arrays . menu_driver ) ? settings - > arrays . menu_driver : " n/a " ) ;
driver =
# ifdef HAVE_THREADS
( video_driver_is_threaded ( ) ) ?
video_thread_get_ident ( ) :
# endif
video_driver_get_ident ( ) ;
if ( string_is_equal ( driver , settings - > arrays . video_driver ) )
filestream_printf ( file , " - Video: %s \n " , ! string_is_empty ( driver ) ? driver : " n/a " ) ;
else
filestream_printf ( file , " - Video: %s (configured for %s) \n " , ! string_is_empty ( driver ) ? driver : " n/a " , ! string_is_empty ( settings - > arrays . video_driver ) ? settings - > arrays . video_driver : " n/a " ) ;
video_context_driver_get_ident ( & ident_info ) ;
filestream_printf ( file , " - Video Context: %s \n " , ident_info . ident ? ident_info . ident : " n/a " ) ;
driver = audio_driver_get_ident ( ) ;
if ( string_is_equal ( driver , settings - > arrays . audio_driver ) )
filestream_printf ( file , " - Audio: %s \n " , ! string_is_empty ( driver ) ? driver : " n/a " ) ;
else
filestream_printf ( file , " - Audio: %s (configured for %s) \n " , ! string_is_empty ( driver ) ? driver : " n/a " , ! string_is_empty ( settings - > arrays . audio_driver ) ? settings - > arrays . audio_driver : " n/a " ) ;
input_driver = input_get_ptr ( ) ;
if ( input_driver & & string_is_equal ( input_driver - > ident , settings - > arrays . input_driver ) )
filestream_printf ( file , " - Input: %s \n " , ! string_is_empty ( input_driver - > ident ) ? input_driver - > ident : " n/a " ) ;
else
filestream_printf ( file , " - Input: %s (configured for %s) \n " , ! string_is_empty ( input_driver - > ident ) ? input_driver - > ident : " n/a " , ! string_is_empty ( settings - > arrays . input_driver ) ? settings - > arrays . input_driver : " n/a " ) ;
joypad_driver = ( input_driver - > get_joypad_driver ? input_driver - > get_joypad_driver ( input_driver_get_data ( ) ) : NULL ) ;
if ( joypad_driver & & string_is_equal ( joypad_driver - > ident , settings - > arrays . input_joypad_driver ) )
filestream_printf ( file , " - Joypad: %s \n " , ! string_is_empty ( joypad_driver - > ident ) ? joypad_driver - > ident : " n/a " ) ;
else
filestream_printf ( file , " - Input: %s (configured for %s) \n " , ! string_is_empty ( joypad_driver - > ident ) ? joypad_driver - > ident : " n/a " , ! string_is_empty ( settings - > arrays . input_joypad_driver ) ? settings - > arrays . input_joypad_driver : " n/a " ) ;
}
filestream_printf ( file , " \n " ) ;
filestream_printf ( file , " Configuration related settings: \n " ) ;
filestream_printf ( file , " - Save on exit: %s \n " , settings - > bools . config_save_on_exit ? " yes " : " no " ) ;
filestream_printf ( file , " - Load content-specific core options automatically: %s \n " , settings - > bools . game_specific_options ? " yes " : " no " ) ;
filestream_printf ( file , " - Load override files automatically: %s \n " , settings - > bools . auto_overrides_enable ? " yes " : " no " ) ;
filestream_printf ( file , " - Load remap files automatically: %s \n " , settings - > bools . auto_remaps_enable ? " yes " : " no " ) ;
filestream_printf ( file , " - Sort saves in folders: %s \n " , settings - > bools . sort_savefiles_enable ? " yes " : " no " ) ;
filestream_printf ( file , " - Sort states in folders: %s \n " , settings - > bools . sort_savestates_enable ? " yes " : " no " ) ;
filestream_printf ( file , " - Write saves in content dir: %s \n " , settings - > bools . savefiles_in_content_dir ? " yes " : " no " ) ;
filestream_printf ( file , " - Write savestates in content dir: %s \n " , settings - > bools . savestates_in_content_dir ? " yes " : " no " ) ;
filestream_printf ( file , " \n " ) ;
filestream_printf ( file , " Auto load state: %s \n " , settings - > bools . savestate_auto_load ? " yes (WARNING: not compatible with all cores) " : " no " ) ;
filestream_printf ( file , " Auto save state: %s \n " , settings - > bools . savestate_auto_save ? " yes " : " no " ) ;
filestream_printf ( file , " \n " ) ;
filestream_printf ( file , " Buildbot cores URL: %s \n " , settings - > paths . network_buildbot_url ) ;
filestream_printf ( file , " Auto-extract downloaded archives: %s \n " , settings - > bools . network_buildbot_auto_extract_archive ? " yes " : " no " ) ;
{
size_t count = 0 ;
core_info_list_t * core_info_list = NULL ;
struct string_list * list = NULL ;
const char * ext = file_path_str ( FILE_PATH_RDB_EXTENSION ) ;
/* remove dot */
if ( ! string_is_empty ( ext ) & & ext [ 0 ] = = ' . ' & & strlen ( ext ) > 1 )
ext + + ;
core_info_get_list ( & core_info_list ) ;
if ( core_info_list )
count = core_info_list - > count ;
filestream_printf ( file , " Core info: %u entries \n " , count ) ;
count = 0 ;
list = dir_list_new ( settings - > paths . path_content_database , ext , false , true , false , true ) ;
if ( list )
{
count = list - > size ;
string_list_free ( list ) ;
}
filestream_printf ( file , " Databases: %u entries \n " , count ) ;
}
filestream_printf ( file , " \n " ) ;
filestream_printf ( file , " Performance and latency-sensitive features (may have a large impact depending on the core): \n " ) ;
filestream_printf ( file , " - Video: \n " ) ;
filestream_printf ( file , " - Runahead: %s \n " , settings - > bools . run_ahead_enabled ? " yes (WARNING: not compatible with all cores) " : " no " ) ;
filestream_printf ( file , " - Rewind: %s \n " , settings - > bools . rewind_enable ? " yes (WARNING: not compatible with all cores) " : " no " ) ;
filestream_printf ( file , " - Hard GPU Sync: %s \n " , settings - > bools . video_hard_sync ? " yes " : " no " ) ;
filestream_printf ( file , " - Frame Delay: %u frames \n " , settings - > uints . video_frame_delay ) ;
filestream_printf ( file , " - Max Swapchain Images: %u \n " , settings - > uints . video_max_swapchain_images ) ;
filestream_printf ( file , " - Max Run Speed: %.1f x \n " , settings - > floats . fastforward_ratio ) ;
filestream_printf ( file , " - Sync to exact content framerate: %s \n " , settings - > bools . vrr_runloop_enable ? " yes (note: designed for G-Sync/FreeSync displays only) " : " no " ) ;
filestream_printf ( file , " - Fullscreen: %s \n " , settings - > bools . video_fullscreen ? " yes " : " no " ) ;
filestream_printf ( file , " - Windowed Fullscreen: %s \n " , settings - > bools . video_windowed_fullscreen ? " yes " : " no " ) ;
filestream_printf ( file , " - Threaded Video: %s \n " , settings - > bools . video_threaded ? " yes " : " no " ) ;
filestream_printf ( file , " - Vsync: %s \n " , settings - > bools . video_vsync ? " yes " : " no " ) ;
filestream_printf ( file , " - Vsync Swap Interval: %u frames \n " , settings - > uints . video_swap_interval ) ;
filestream_printf ( file , " - Black Frame Insertion: %s \n " , settings - > bools . video_black_frame_insertion ? " yes " : " no " ) ;
filestream_printf ( file , " - Bilinear Filtering: %s \n " , settings - > bools . video_smooth ? " yes " : " no " ) ;
filestream_printf ( file , " - Video CPU Filter: %s \n " , ! string_is_empty ( settings - > paths . path_softfilter_plugin ) ? settings - > paths . path_softfilter_plugin : " n/a " ) ;
filestream_printf ( file , " - CRT SwitchRes: %s \n " , ( settings - > uints . crt_switch_resolution > CRT_SWITCH_NONE ) ? " yes " : " no " ) ;
filestream_printf ( file , " - Video Shared Context: %s \n " , settings - > bools . video_shared_context ? " yes " : " no " ) ;
{
video_shader_ctx_t shader_info = { 0 } ;
video_shader_driver_get_current_shader ( & shader_info ) ;
if ( shader_info . data )
{
if ( string_is_equal ( shader_info . data - > path , settings - > paths . path_shader ) )
filestream_printf ( file , " - Video Shader: %s \n " , ! string_is_empty ( settings - > paths . path_shader ) ? settings - > paths . path_shader : " n/a " ) ;
else
filestream_printf ( file , " - Video Shader: %s (configured for %s) \n " , ! string_is_empty ( shader_info . data - > path ) ? shader_info . data - > path : " n/a " , ! string_is_empty ( settings - > paths . path_shader ) ? settings - > paths . path_shader : " n/a " ) ;
}
else
filestream_printf ( file , " - Video Shader: n/a \n " ) ;
}
filestream_printf ( file , " - Audio: \n " ) ;
filestream_printf ( file , " - Audio Enabled: %s \n " , settings - > bools . audio_enable ? " yes " : " no (WARNING: content framerate will be incorrect) " ) ;
filestream_printf ( file , " - Audio Sync: %s \n " , settings - > bools . audio_sync ? " yes " : " no (WARNING: content framerate will be incorrect) " ) ;
{
const char * s = NULL ;
switch ( settings - > uints . audio_resampler_quality )
{
case RESAMPLER_QUALITY_DONTCARE :
s = msg_hash_to_str ( MENU_ENUM_LABEL_VALUE_DONT_CARE ) ;
break ;
case RESAMPLER_QUALITY_LOWEST :
s = msg_hash_to_str ( MSG_RESAMPLER_QUALITY_LOWEST ) ;
break ;
case RESAMPLER_QUALITY_LOWER :
s = msg_hash_to_str ( MSG_RESAMPLER_QUALITY_LOWER ) ;
break ;
case RESAMPLER_QUALITY_HIGHER :
s = msg_hash_to_str ( MSG_RESAMPLER_QUALITY_HIGHER ) ;
break ;
case RESAMPLER_QUALITY_HIGHEST :
s = msg_hash_to_str ( MSG_RESAMPLER_QUALITY_HIGHEST ) ;
break ;
case RESAMPLER_QUALITY_NORMAL :
s = msg_hash_to_str ( MSG_RESAMPLER_QUALITY_NORMAL ) ;
break ;
}
filestream_printf ( file , " - Resampler Quality: %s \n " , ! string_is_empty ( s ) ? s : " n/a " ) ;
}
filestream_printf ( file , " - Audio Latency: %u ms \n " , settings - > uints . audio_latency ) ;
filestream_printf ( file , " - Dynamic Rate Control (DRC): %.3f \n " , * audio_get_float_ptr ( AUDIO_ACTION_RATE_CONTROL_DELTA ) ) ;
filestream_printf ( file , " - Max Timing Skew: %.2f \n " , settings - > floats . audio_max_timing_skew ) ;
filestream_printf ( file , " - Output Rate: %u Hz \n " , settings - > uints . audio_out_rate ) ;
filestream_printf ( file , " - DSP Plugin: %s \n " , ! string_is_empty ( settings - > paths . path_audio_dsp_plugin ) ? settings - > paths . path_audio_dsp_plugin : " n/a " ) ;
2019-03-09 17:57:26 +00:00
{
core_info_list_t * core_info_list = NULL ;
bool found = false ;
filestream_printf ( file , " \n " ) ;
filestream_printf ( file , " Firmware files found: \n " ) ;
core_info_get_list ( & core_info_list ) ;
if ( core_info_list )
{
2019-03-11 16:07:49 +00:00
unsigned i ;
2019-03-09 17:57:26 +00:00
for ( i = 0 ; i < core_info_list - > count ; i + + )
{
core_info_t * info = & core_info_list - > list [ i ] ;
if ( ! info )
continue ;
if ( info - > firmware_count )
{
2019-03-11 16:07:49 +00:00
unsigned j ;
2019-03-09 17:57:26 +00:00
bool core_found = false ;
for ( j = 0 ; j < info - > firmware_count ; j + + )
{
core_info_firmware_t * firmware = & info - > firmware [ j ] ;
char path [ PATH_MAX_LENGTH ] ;
if ( ! firmware )
continue ;
path [ 0 ] = ' \0 ' ;
fill_pathname_join (
path ,
settings - > paths . directory_system ,
firmware - > path ,
sizeof ( path ) ) ;
if ( filestream_exists ( path ) )
{
found = true ;
if ( ! core_found )
{
core_found = true ;
filestream_printf ( file , " - %s: \n " , ! string_is_empty ( info - > core_name ) ? info - > core_name : path_basename ( info - > path ) ) ;
}
filestream_printf ( file , " - %s (%s) \n " , firmware - > path , firmware - > optional ? " optional " : " required " ) ;
}
}
}
}
}
if ( ! found )
filestream_printf ( file , " - n/a \n " ) ;
}
2019-03-08 00:17:54 +00:00
filestream_close ( file ) ;
RARCH_LOG ( " Wrote debug info to %s \n " , debug_filepath ) ;
msg_hash_set_uint ( MSG_HASH_USER_LANGUAGE , lang ) ;
return true ;
error :
return false ;
}
2019-03-11 15:58:43 +00:00
# ifdef HAVE_NETWORKING
2019-03-08 00:17:54 +00:00
static void send_debug_info_cb ( retro_task_t * task ,
void * task_data , void * user_data , const char * error )
{
if ( task_data )
{
http_transfer_data_t * data = ( http_transfer_data_t * ) task_data ;
if ( ! data | | data - > len = = 0 )
{
RARCH_LOG ( " %s \n " , msg_hash_to_str ( MSG_FAILED_TO_SEND_DEBUG_INFO ) ) ;
runloop_msg_queue_push (
msg_hash_to_str ( MSG_FAILED_TO_SEND_DEBUG_INFO ) ,
2 , 180 , true ,
NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_ERROR ) ;
free ( task_data ) ;
return ;
}
/* don't use string_is_equal() here instead of the memcmp() because the data isn't NULL-terminated */
if ( ! string_is_empty ( data - > data ) & & data - > len > = 2 & & ! memcmp ( data - > data , " OK " , 2 ) )
{
char buf [ 32 ] = { 0 } ;
struct string_list * list ;
memcpy ( buf , data - > data , data - > len ) ;
list = string_split ( buf , " " ) ;
if ( list & & list - > size > 1 )
{
unsigned id = 0 ;
char msg [ PATH_MAX_LENGTH ] ;
msg [ 0 ] = ' \0 ' ;
sscanf ( list - > elems [ 1 ] . data , " %u " , & id ) ;
snprintf ( msg , sizeof ( msg ) , msg_hash_to_str ( MSG_SENT_DEBUG_INFO ) , id ) ;
RARCH_LOG ( " %s \n " , msg ) ;
runloop_msg_queue_push (
msg ,
2 , 600 , true ,
NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_INFO ) ;
}
if ( list )
string_list_free ( list ) ;
}
else
{
RARCH_LOG ( " %s \n " , msg_hash_to_str ( MSG_FAILED_TO_SEND_DEBUG_INFO ) ) ;
runloop_msg_queue_push (
msg_hash_to_str ( MSG_FAILED_TO_SEND_DEBUG_INFO ) ,
2 , 180 , true ,
NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_ERROR ) ;
}
free ( task_data ) ;
}
else
{
RARCH_LOG ( " %s \n " , msg_hash_to_str ( MSG_FAILED_TO_SEND_DEBUG_INFO ) ) ;
runloop_msg_queue_push (
msg_hash_to_str ( MSG_FAILED_TO_SEND_DEBUG_INFO ) ,
2 , 180 , true ,
NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_ERROR ) ;
}
}
2019-03-11 15:58:43 +00:00
# endif
2019-03-08 00:17:54 +00:00
void rarch_send_debug_info ( void )
{
2019-03-11 15:58:43 +00:00
# ifdef HAVE_NETWORKING
2019-03-08 00:17:54 +00:00
const char * url = " http://lobby.libretro.com/debuginfo/add/ " ;
char * info_buf = NULL ;
const size_t param_buf_size = 65535 ;
char * param_buf = ( char * ) malloc ( param_buf_size ) ;
char * param_buf_tmp = NULL ;
int param_buf_pos = 0 ;
int64_t len = 0 ;
char debug_filepath [ PATH_MAX_LENGTH ] ;
const char * path_config = path_get ( RARCH_PATH_CONFIG ) ;
bool info_written = rarch_write_debug_info ( ) ;
debug_filepath [ 0 ] = param_buf [ 0 ] = ' \0 ' ;
fill_pathname_resolve_relative (
debug_filepath ,
path_config ,
DEBUG_INFO_FILENAME ,
sizeof ( debug_filepath ) ) ;
if ( info_written )
filestream_read_file ( debug_filepath , ( void * * ) & info_buf , & len ) ;
if ( string_is_empty ( info_buf ) | | len = = 0 | | ! info_written )
{
runloop_msg_queue_push (
msg_hash_to_str ( MSG_FAILED_TO_SAVE_DEBUG_INFO ) ,
2 , 180 , true ,
NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_ERROR ) ;
goto finish ;
}
RARCH_LOG ( " %s \n " , msg_hash_to_str ( MSG_SENDING_DEBUG_INFO ) ) ;
runloop_msg_queue_push (
msg_hash_to_str ( MSG_SENDING_DEBUG_INFO ) ,
2 , 180 , true ,
NULL , MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_INFO ) ;
param_buf_pos = strlcpy ( param_buf , " info= " , param_buf_size ) ;
param_buf_tmp = param_buf + param_buf_pos ;
net_http_urlencode ( & param_buf_tmp , info_buf ) ;
strlcat ( param_buf , param_buf_tmp , param_buf_size - param_buf_pos ) ;
task_push_http_post_transfer ( url , param_buf , true , NULL , send_debug_info_cb , NULL ) ;
finish :
if ( param_buf )
free ( param_buf ) ;
if ( info_buf )
free ( info_buf ) ;
2019-03-11 15:58:43 +00:00
# endif
2019-03-08 00:17:54 +00:00
}
2019-03-21 16:56:24 +00:00
void rarch_log_file_init ( void )
{
settings_t * settings = config_get_ptr ( ) ;
FILE * fp = NULL ;
2019-03-25 17:22:59 +00:00
/* If this is the first run, generate a timestamped log
* file name ( do this even when not outputting timestamped
* log files , since user may decide to switch at any moment . . . ) */
if ( string_is_empty ( timestamped_log_file_name ) )
{
char format [ 256 ] ;
time_t cur_time = time ( NULL ) ;
format [ 0 ] = ' \0 ' ;
strftime ( format , sizeof ( format ) , " retroarch__%Y_%m_%d__%H_%M_%S " , localtime ( & cur_time ) ) ;
fill_pathname_noext ( timestamped_log_file_name , format ,
file_path_str ( FILE_PATH_EVENT_LOG_EXTENSION ) , sizeof ( timestamped_log_file_name ) ) ;
}
2019-03-21 16:56:24 +00:00
/* If nothing has changed, do nothing */
if ( ( ! settings - > bools . log_to_file & & ! is_logging_to_file ( ) ) | |
( settings - > bools . log_to_file & & is_logging_to_file ( ) ) )
return ;
/* If we are currently logging to file and wish to stop,
* de - initialise existing logger . . . */
if ( ! settings - > bools . log_to_file & & is_logging_to_file ( ) )
{
retro_main_log_file_deinit ( ) ;
/* ...and revert to console */
retro_main_log_file_init ( NULL , false ) ;
return ;
}
/* If we reach this point, then we are not currently
* logging to file , and wish to do so */
/* > Check whether we are already logging to console */
fp = retro_main_log_file ( ) ;
if ( fp )
{
/* De-initialise existing logger */
retro_main_log_file_deinit ( ) ;
}
/* > Attempt to initialise log file */
if ( ! string_is_empty ( settings - > paths . log_dir ) )
{
2019-03-28 11:27:26 +00:00
/* Create log directory, if required */
if ( ! path_is_directory ( settings - > paths . log_dir ) )
{
path_mkdir ( settings - > paths . log_dir ) ;
if ( ! path_is_directory ( settings - > paths . log_dir ) )
{
/* Re-enable console logging and output error message */
retro_main_log_file_init ( NULL , false ) ;
RARCH_ERR ( " Failed to create system event log directory: %s \n " , settings - > paths . log_dir ) ;
return ;
}
}
/* Format log file name */
2019-03-21 16:56:24 +00:00
char buf [ PATH_MAX_LENGTH ] ;
2019-03-25 17:22:59 +00:00
fill_pathname_join ( buf , settings - > paths . log_dir ,
settings - > bools . log_to_file_timestamp ? timestamped_log_file_name : file_path_str ( FILE_PATH_DEFAULT_EVENT_LOG ) ,
sizeof ( buf ) ) ;
2019-03-21 16:56:24 +00:00
if ( ! string_is_empty ( buf ) )
{
/* When RetroArch is launched, log file is overwritten.
* On subsequent calls within the same session , it is appended to . */
retro_main_log_file_init ( buf , log_file_created ) ;
2019-03-28 11:27:26 +00:00
if ( is_logging_to_file ( ) )
log_file_created = true ;
return ;
2019-03-21 16:56:24 +00:00
}
}
2019-03-28 11:27:26 +00:00
/* If we reach this point, then something went wrong...
* Just fall back to console logging */
retro_main_log_file_init ( NULL , false ) ;
RARCH_ERR ( " Failed to initialise system event file logging... \n " ) ;
2019-03-21 16:56:24 +00:00
}
void rarch_log_file_deinit ( void )
{
FILE * fp = NULL ;
/* De-initialise existing logger, if currently logging to file */
if ( is_logging_to_file ( ) )
{
retro_main_log_file_deinit ( ) ;
}
/* If logging is currently disabled... */
fp = retro_main_log_file ( ) ;
if ( ! fp )
{
/* ...initialise logging to console */
retro_main_log_file_init ( NULL , false ) ;
}
}