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
2016-01-10 03:06:50 +00:00
* Copyright ( C ) 2011 - 2016 - Daniel De Matteis
2015-01-07 16:46:50 +00:00
* Copyright ( C ) 2012 - 2015 - Michael Lelli
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/>.
*/
2010-05-26 19:27:37 +00:00
# include <stdlib.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>
2014-10-22 02:27:51 +00:00
# include <boolean.h>
2015-12-26 06:07:01 +00:00
# include <string/stdstring.h>
2015-06-14 14:45:20 +00:00
# ifdef _WIN32
# ifdef _XBOX
# include <xtl.h>
# else
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# endif
# endif
# include <compat/strl.h>
# include <compat/getopt.h>
# include <compat/posix_string.h>
# include <file/file_path.h>
2015-09-21 23:45:16 +00:00
# include <retro_stat.h>
2015-06-14 14:45:20 +00:00
2016-01-19 22:15:19 +00:00
# include "content.h"
2015-12-07 07:56:11 +00:00
# include "core_info.h"
2015-07-01 17:30:34 +00:00
# include "msg_hash.h"
2015-12-01 00:47:26 +00:00
# include "movie.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"
2015-12-05 15:12:29 +00:00
# include "record/record_driver.h"
2015-01-13 01:29:08 +00:00
# include "libretro_version_1.h"
2015-12-05 16:19:37 +00:00
# include "libretro_private.h"
2015-04-07 01:22:33 +00:00
# include "configuration.h"
2010-12-24 00:26:36 +00:00
# include "general.h"
2015-11-30 14:35:57 +00:00
# include "runloop.h"
2015-11-24 19:44:45 +00:00
# include "tasks/tasks.h"
2014-10-12 17:45:38 +00:00
# include "performance.h"
2011-04-17 11:30:59 +00:00
# include "cheats.h"
2015-06-25 09:02:01 +00:00
# include "system.h"
2015-10-20 15:20:56 +00:00
# include "retro_file.h"
2015-01-24 22:42:31 +00:00
2014-01-11 17:51:42 +00:00
# include "git_version.h"
2010-12-24 00:07:27 +00:00
2015-10-27 23:55:11 +00:00
# include "retroarch.h"
2015-11-30 22:35:04 +00:00
# ifdef HAVE_COMMAND
# include "command.h"
# endif
2014-07-22 01:12:56 +00:00
# ifdef HAVE_MENU
2015-12-06 16:55:27 +00:00
# include "menu/menu_driver.h"
2016-01-25 03:44:54 +00:00
# include "menu/menu_content.h"
2015-06-14 14:45:20 +00:00
# include "menu/menu_hash.h"
2014-07-22 01:12:56 +00:00
# endif
2015-11-30 03:10:15 +00:00
# include "config.features.h"
2016-01-02 01:54:20 +00:00
# include "command_event.h"
2015-10-20 00:43:21 +00:00
2015-06-12 15:42:44 +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 */
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 ,
RA_OPT_LOG_FILE ,
2015-06-18 00:30:53 +00:00
RA_OPT_MAX_FRAMES
2015-06-12 15:42:44 +00:00
} ;
2016-01-20 02:15:50 +00:00
static enum rarch_core_type current_core_type ;
2015-11-30 18:30:05 +00:00
static char current_savefile_dir [ PATH_MAX_LENGTH ] ;
static char error_string [ PATH_MAX_LENGTH ] ;
static jmp_buf error_sjlj_context ;
2015-06-12 13:16:57 +00:00
# define _PSUPP(var, name, desc) printf(" %s:\n\t\t%s: %s\n", name, desc, _##var##_supp ? "yes" : "no")
2015-11-30 03:10:15 +00:00
2011-01-25 12:03:53 +00:00
static void print_features ( void )
{
puts ( " " ) ;
puts ( " Features: " ) ;
2015-04-16 19:58:19 +00:00
_PSUPP ( libretrodb , " LibretroDB " , " LibretroDB support " ) ;
_PSUPP ( command , " Command " , " Command interface support " ) ;
_PSUPP ( network_command , " Network Command " , " Network Command interface support " ) ;
2015-04-19 16:41:11 +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 " ) ;
2011-11-30 16:46:58 +00:00
_PSUPP ( thread , " Threads " , " Threading support " ) ;
2011-11-01 17:45:50 +00:00
_PSUPP ( opengl , " OpenGL " , " OpenGL driver " ) ;
2015-04-16 20:13:16 +00:00
_PSUPP ( opengles , " OpenGL ES " , " OpenGL ES driver " ) ;
2015-04-19 18:42:54 +00:00
_PSUPP ( xvideo , " XVideo " , " Video driver " ) ;
2013-12-08 15:07:14 +00:00
_PSUPP ( udev , " UDEV " , " UDEV/EVDEV input driver support " ) ;
2015-04-19 16:44:28 +00:00
_PSUPP ( egl , " EGL " , " video context driver " ) ;
_PSUPP ( kms , " KMS " , " video context driver " ) ;
_PSUPP ( vg , " OpenVG " , " video context driver " ) ;
2015-04-19 18:42:54 +00:00
_PSUPP ( coreaudio , " CoreAudio " , " Audio driver " ) ;
_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 " ) ;
_PSUPP ( xaudio , " XAudio2 " , " Audio driver " ) ;
_PSUPP ( al , " OpenAL " , " Audio driver " ) ;
_PSUPP ( sl , " OpenSL " , " Audio driver " ) ;
2015-04-19 16:41:11 +00:00
_PSUPP ( 7 zip , " 7zip " , " 7zip support " ) ;
_PSUPP ( zlib , " zlib " , " .zip extraction " ) ;
2012-12-22 10:35:26 +00:00
_PSUPP ( dylib , " External " , " External filter and plugin support " ) ;
2015-04-19 18:42:54 +00:00
_PSUPP ( cg , " Cg " , " Fragment/vertex shader driver " ) ;
_PSUPP ( glsl , " GLSL " , " Fragment/vertex shader driver " ) ;
_PSUPP ( glsl , " HLSL " , " Fragment/vertex shader driver " ) ;
2013-01-02 14:05:55 +00:00
_PSUPP ( libxml2 , " libxml2 " , " libxml2 XML parsing " ) ;
2011-06-11 14:55:53 +00:00
_PSUPP ( sdl_image , " SDL_image " , " SDL_image image loading " ) ;
2015-04-19 16:41:11 +00:00
_PSUPP ( rpng , " rpng " , " PNG image loading/encoding " ) ;
2011-03-23 22:48:13 +00:00
_PSUPP ( fbo , " FBO " , " OpenGL render-to-texture (multi-pass shaders) " ) ;
2012-04-03 17:25:53 +00:00
_PSUPP ( dynamic , " Dynamic " , " Dynamic run-time loading of libretro library " ) ;
2011-01-25 12:03:53 +00:00
_PSUPP ( ffmpeg , " FFmpeg " , " On-the-fly recording of gameplay with libavcodec " ) ;
2015-04-19 18:42:54 +00:00
_PSUPP ( freetype , " FreeType " , " TTF font rendering driver " ) ;
_PSUPP ( coretext , " CoreText " , " TTF font rendering driver (for OSX and/or iOS) " ) ;
2011-03-19 19:41:07 +00:00
_PSUPP ( netplay , " Netplay " , " Peer-to-peer netplay " ) ;
2011-06-06 18:21:26 +00:00
_PSUPP ( python , " Python " , " Script support in shaders " ) ;
2015-04-16 19:58:19 +00:00
_PSUPP ( libusb , " Libusb " , " Libusb support " ) ;
2015-04-19 16:41:11 +00:00
_PSUPP ( cocoa , " Cocoa " , " Cocoa UI companion support (for OSX and/or iOS) " ) ;
_PSUPP ( qt , " QT " , " QT UI companion support " ) ;
2015-04-19 18:42:54 +00:00
_PSUPP ( avfoundation , " AVFoundation " , " Camera driver " ) ;
_PSUPP ( v4l2 , " Video4Linux2 " , " Camera driver " ) ;
2011-01-25 12:03:53 +00:00
}
# undef _PSUPP
2015-06-12 14:42:29 +00:00
static void print_version ( void )
2010-10-01 19:39:15 +00:00
{
2015-06-12 15:00:37 +00:00
char str [ PATH_MAX_LENGTH ] = { 0 } ;
2015-04-16 18:17:05 +00:00
2015-07-02 22:16:46 +00:00
fprintf ( stderr , " %s: Frontend for libretro -- v%s " , msg_hash_to_str ( MSG_PROGRAM ) , PACKAGE_VERSION ) ;
2014-01-11 17:51:42 +00:00
# ifdef HAVE_GIT_VERSION
2015-07-02 22:16:46 +00:00
printf ( " -- %s -- \n " , rarch_git_version ) ;
2014-01-11 17:51:42 +00:00
# endif
2015-05-13 11:21:43 +00:00
rarch_info_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
}
/**
* print_help :
*
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
* */
static void print_help ( const char * arg0 )
{
2015-06-12 15:43:38 +00:00
puts ( " =================================================================== " ) ;
2015-06-12 14:42:29 +00:00
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 ( " --log-file=FILE Log messages to FILE. " ) ;
puts ( " --version Show version. " ) ;
puts ( " --features Prints available features compiled into program. " ) ;
2015-10-28 07:02:39 +00:00
# ifdef HAVE_MENU
2015-06-12 14:18:36 +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 "
2015-07-02 22:16:46 +00:00
" 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). " ) ;
2015-07-02 22:16:46 +00:00
puts ( " -f, --fullscreen Start the program in fullscreen regardless of config settings. " ) ;
puts ( " -c, --config=FILE Path for config file. "
# ifdef _WIN32
" \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. "
# else
" \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, the program will attempt to create one based on the skeleton config ( " GLOBAL_CONFIG_DIR " /retroarch.cfg). "
# endif
) ;
2015-06-12 14:18:36 +00:00
puts ( " --appendconfig=FILE \n "
" Extra config files are loaded in, and take priority over \n "
" config selected in -c (or default). Multiple configs are \n "
" delimited by '|'. " ) ;
2011-11-15 20:15:12 +00:00
# ifdef HAVE_DYNAMIC
2015-06-12 14:18:36 +00:00
puts ( " -L, --libretro=FILE Path to libretro implementation. Overrides any config setting. " ) ;
2011-01-19 11:54:19 +00:00
# endif
2015-06-12 14:18:36 +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 "
" Disconnects controller device connected to PORT (1 to %d). \n " , MAX_USERS ) ;
printf ( " -A, --dualanalog=PORT \n "
" Connect a DualAnalog controller to PORT (1 to %d). \n " , MAX_USERS ) ;
printf ( " -d, --device=PORT:ID \n "
" 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. " ) ;
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
2011-03-19 19:41:07 +00:00
# ifdef HAVE_NETPLAY
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. " ) ;
puts ( " -F, --frames=NUMBER Sync frames when using netplay. " ) ;
puts ( " --spectate Connect to netplay server as spectator. " ) ;
2011-03-19 19:41:07 +00:00
# endif
2015-06-12 14:18:36 +00:00
puts ( " --nick=NICK Picks a username (for use with netplay). Not mandatory. " ) ;
2014-08-02 02:21:07 +00:00
# if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY)
2015-07-02 22:16:46 +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
2015-06-12 14:18:36 +00:00
puts ( " -r, --record=FILE Path to record video file. \n Using .mkv extension is recommended. " ) ;
puts ( " --recordconfig Path to settings used during recording. " ) ;
puts ( " --size=WIDTHxHEIGHT \n "
" Overrides output video size when recording. " ) ;
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. " ) ;
puts ( " --no-patch Disables all forms of content patching. " ) ;
2015-07-02 22:16:46 +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 "
" Runs for the specified number of frames, then exits. \n " ) ;
2010-10-01 19:39:15 +00:00
}
2011-02-11 13:27:19 +00:00
static void set_basename ( const char * path )
{
2015-03-22 06:28:45 +00:00
char * dst = NULL ;
2015-03-21 03:43:18 +00:00
global_t * global = global_get_ptr ( ) ;
2011-10-27 21:40:34 +00:00
2015-11-30 20:42:59 +00:00
runloop_ctl ( RUNLOOP_CTL_SET_CONTENT_PATH , ( void * ) path ) ;
2015-09-20 09:12:22 +00:00
strlcpy ( global - > name . base , path , sizeof ( global - > name . base ) ) ;
2014-12-15 16:21:25 +00:00
# ifdef HAVE_COMPRESSION
2014-09-17 17:46:59 +00:00
/* Removing extension is a bit tricky for compressed files.
* Basename means :
* / file / to / path / game . extension should be :
* / file / to / path / game
*
* Two things to consider here are : / file / to / path / is expected
* to be a directory and " game " is a single file . This is used for
2014-12-15 16:21:25 +00:00
* states and srm default paths .
2014-09-17 17:46:59 +00:00
*
* For compressed files we have :
*
* / file / to / path / comp .7 z # game . extension and
* / file / to / path / comp .7 z # folder / game . extension
*
* The choice I take here is :
2015-05-07 23:06:14 +00:00
* / file / to / path / game as basename . We might end up in a writable
2014-12-15 16:21:25 +00:00
* directory then and the name of srm and states are meaningful .
2014-09-17 17:46:59 +00:00
*
*/
2015-07-27 15:18:10 +00:00
path_basedir ( global - > name . base ) ;
fill_pathname_dir ( global - > name . base , path , " " , sizeof ( global - > name . base ) ) ;
2014-09-17 17:46:59 +00:00
# endif
2014-08-02 09:48:42 +00:00
2015-07-27 15:18:10 +00:00
if ( ( dst = strrchr ( global - > name . base , ' . ' ) ) )
2011-02-11 13:27:19 +00:00
* dst = ' \0 ' ;
}
2014-07-28 17:47:12 +00:00
static void set_special_paths ( char * * argv , unsigned num_content )
2014-04-04 12:58:42 +00:00
{
unsigned i ;
2014-08-02 09:48:42 +00:00
union string_list_elem_attr attr ;
2015-03-21 03:43:18 +00:00
global_t * global = global_get_ptr ( ) ;
2015-03-20 19:20:33 +00:00
settings_t * settings = config_get_ptr ( ) ;
2014-04-04 12:58:42 +00:00
2014-08-20 15:18:43 +00:00
/* First content file is the significant one. */
2014-04-04 12:58:42 +00:00
set_basename ( argv [ 0 ] ) ;
2015-03-21 03:43:18 +00:00
global - > subsystem_fullpaths = string_list_new ( ) ;
2015-10-26 02:18:13 +00:00
retro_assert ( global - > subsystem_fullpaths ) ;
2014-04-04 12:58:42 +00:00
attr . i = 0 ;
2014-07-28 17:47:12 +00:00
for ( i = 0 ; i < num_content ; i + + )
2015-03-21 03:43:18 +00:00
string_list_append ( global - > subsystem_fullpaths , argv [ i ] , attr ) ;
2014-04-04 12:58:42 +00:00
2014-08-20 15:18:43 +00:00
/* We defer SRAM path updates until we can resolve it.
2014-08-31 23:37:44 +00:00
* It is more complicated for special content types . */
2014-04-04 12:58:42 +00:00
2015-07-27 15:18:10 +00:00
if ( ! global - > has_set . state_path )
fill_pathname_noext ( global - > name . savestate , global - > name . base ,
" .state " , sizeof ( global - > name . savestate ) ) ;
2014-04-04 12:58:42 +00:00
2015-07-27 15:18:10 +00:00
if ( path_is_directory ( global - > name . savestate ) )
2014-04-04 12:58:42 +00:00
{
2015-07-27 15:18:10 +00:00
fill_pathname_dir ( global - > name . savestate , global - > name . base ,
" .state " , sizeof ( global - > name . savestate ) ) ;
2015-07-01 17:30:34 +00:00
RARCH_LOG ( " %s \" %s \" . \n " ,
msg_hash_to_str ( MSG_REDIRECTING_SAVESTATE_TO ) ,
2015-07-27 15:18:10 +00:00
global - > name . savestate ) ;
2014-04-04 12:58:42 +00:00
}
2014-08-20 15:18:43 +00:00
/* If this is already set,
* do not overwrite it as this was initialized before in
2014-09-02 00:55:43 +00:00
* a menu or otherwise . */
2015-12-26 06:07:01 +00:00
if ( string_is_empty ( settings - > system_directory ) )
2015-07-16 06:45:49 +00:00
{
RARCH_WARN ( " SYSTEM DIR is empty, assume CONTENT DIR %s \n " , argv [ 0 ] ) ;
2015-07-26 21:23:41 +00:00
/*fill_pathname_basedir(settings->system_directory, argv[0],
sizeof ( settings - > system_directory ) ) ; */
2015-07-16 06:45:49 +00:00
}
2015-11-30 03:10:15 +00:00
}
2015-07-26 21:23:41 +00:00
2015-11-30 03:10:15 +00:00
const char * rarch_get_current_savefile_dir ( void )
{
RARCH_LOG ( " Environ SAVE_DIRECTORY: \" %s \" . \n " ,
current_savefile_dir ) ;
if ( * current_savefile_dir )
return current_savefile_dir ;
return NULL ;
2014-04-04 12:58:42 +00:00
}
2015-12-07 13:30:36 +00:00
static void set_paths_redirect ( const char * path )
2011-08-24 13:47:39 +00:00
{
2015-12-26 08:56:53 +00:00
char current_savestate_dir [ PATH_MAX_LENGTH ] ;
2015-12-10 21:30:25 +00:00
uint32_t global_library_name_hash = 0 ;
2015-12-04 09:58:18 +00:00
bool check_global_library_name_hash = false ;
global_t * global = global_get_ptr ( ) ;
settings_t * settings = config_get_ptr ( ) ;
2015-12-10 21:30:25 +00:00
rarch_system_info_t * info = NULL ;
runloop_ctl ( RUNLOOP_CTL_SYSTEM_INFO_GET , & info ) ;
2015-12-25 06:04:15 +00:00
if ( ! global )
{
RARCH_WARN ( " set_paths_redirect was sent a NULL \" global \" pointer. " ) ;
return ;
}
if ( info - > info . library_name & &
2015-12-26 06:07:01 +00:00
! string_is_empty ( info - > info . library_name ) )
2015-12-10 21:30:25 +00:00
global_library_name_hash = msg_hash_calculate ( info - > info . library_name ) ;
2015-05-07 23:06:14 +00:00
2015-11-30 03:10:15 +00:00
/* Initialize current save directories with the values from the config */
strlcpy ( current_savefile_dir ,
global - > dir . savefile ,
sizeof ( current_savefile_dir ) ) ;
strlcpy ( current_savestate_dir ,
global - > dir . savestate ,
sizeof ( current_savestate_dir ) ) ;
2015-10-22 18:37:33 +00:00
2015-12-04 09:58:18 +00:00
check_global_library_name_hash = ( global_library_name_hash ! = 0 ) ;
2015-10-27 23:55:11 +00:00
# ifdef HAVE_MENU
2015-12-04 09:58:18 +00:00
check_global_library_name_hash = check_global_library_name_hash & &
( global_library_name_hash ! = MENU_VALUE_NO_CORE ) ;
2015-10-27 23:55:11 +00:00
# endif
2015-12-04 09:58:18 +00:00
if ( check_global_library_name_hash )
2015-05-07 23:06:14 +00:00
{
2015-06-14 14:45:20 +00:00
/* per-core saves: append the library_name to the save location */
2015-12-26 06:07:01 +00:00
if ( settings - > sort_savefiles_enable
& & ! string_is_empty ( global - > dir . savefile ) )
2015-06-14 14:45:20 +00:00
{
2015-10-20 00:43:21 +00:00
fill_pathname_join (
current_savefile_dir ,
2015-07-27 15:18:10 +00:00
global - > dir . savefile ,
2015-06-25 10:36:55 +00:00
info - > info . library_name ,
2015-07-27 15:18:10 +00:00
sizeof ( global - > dir . savefile ) ) ;
2015-06-14 14:45:20 +00:00
2015-06-26 14:04:42 +00:00
/* If path doesn't exist, try to create it,
* if everything fails revert to the original path . */
2015-12-26 06:07:01 +00:00
if ( ! path_is_directory ( current_savefile_dir )
& & ! string_is_empty ( current_savefile_dir ) )
2015-09-25 04:11:14 +00:00
{
2015-10-20 00:43:21 +00:00
path_mkdir ( current_savefile_dir ) ;
if ( ! path_is_directory ( current_savefile_dir ) )
2015-09-25 04:11:14 +00:00
{
2015-10-20 00:43:21 +00:00
RARCH_LOG ( " Reverting savefile directory to %s \n " , global - > dir . savefile ) ;
strlcpy ( current_savefile_dir ,
global - > dir . savefile ,
sizeof ( current_savefile_dir ) ) ;
2015-09-25 04:11:14 +00:00
}
}
2015-06-14 14:45:20 +00:00
}
2015-05-08 01:16:51 +00:00
2015-06-14 14:45:20 +00:00
/* per-core states: append the library_name to the save location */
2015-12-26 06:07:01 +00:00
if ( settings - > sort_savestates_enable
& & ! string_is_empty ( global - > dir . savestate ) )
2015-06-14 14:45:20 +00:00
{
2015-10-20 00:43:21 +00:00
fill_pathname_join (
current_savestate_dir ,
2015-07-27 15:18:10 +00:00
global - > dir . savestate ,
2015-06-25 10:36:55 +00:00
info - > info . library_name ,
2015-07-27 15:18:10 +00:00
sizeof ( global - > dir . savestate ) ) ;
2015-06-14 14:45:20 +00:00
/* If path doesn't exist, try to create it.
* If everything fails , revert to the original path . */
2015-12-26 06:07:01 +00:00
if ( ! path_is_directory ( current_savestate_dir ) & &
! string_is_empty ( current_savestate_dir ) )
2015-09-25 04:11:14 +00:00
{
2015-10-20 00:43:21 +00:00
path_mkdir ( current_savestate_dir ) ;
if ( ! path_is_directory ( current_savestate_dir ) )
2015-09-25 04:11:14 +00:00
{
2015-10-20 00:43:21 +00:00
RARCH_LOG ( " Reverting savestate directory to %s \n " , global - > dir . savestate ) ;
strlcpy ( current_savestate_dir ,
global - > dir . savestate ,
sizeof ( current_savestate_dir ) ) ;
2015-09-25 04:11:14 +00:00
}
}
2015-06-14 14:45:20 +00:00
}
2015-05-07 23:06:14 +00:00
}
2015-03-21 03:43:18 +00:00
2015-10-20 00:43:21 +00:00
if ( path_is_directory ( current_savefile_dir ) )
strlcpy ( global - > name . savefile , current_savefile_dir ,
2015-07-27 15:18:10 +00:00
sizeof ( global - > name . savefile ) ) ;
2015-05-07 05:36:29 +00:00
2015-10-20 00:43:21 +00:00
if ( path_is_directory ( current_savestate_dir ) )
strlcpy ( global - > name . savestate , current_savestate_dir ,
2015-07-27 15:18:10 +00:00
sizeof ( global - > name . savestate ) ) ;
2015-05-07 05:38:13 +00:00
2015-07-27 15:18:10 +00:00
if ( path_is_directory ( global - > name . savefile ) )
2011-08-24 13:47:39 +00:00
{
2015-07-27 15:18:10 +00:00
fill_pathname_dir ( global - > name . savefile , global - > name . base ,
" .srm " , sizeof ( global - > name . savefile ) ) ;
2015-07-01 17:30:34 +00:00
RARCH_LOG ( " %s \" %s \" . \n " ,
msg_hash_to_str ( MSG_REDIRECTING_SAVEFILE_TO ) ,
2015-07-27 15:18:10 +00:00
global - > name . savefile ) ;
2011-08-24 13:47:39 +00:00
}
2015-05-07 23:06:14 +00:00
2015-07-27 15:18:10 +00:00
if ( path_is_directory ( global - > name . savestate ) )
2011-08-24 13:47:39 +00:00
{
2015-07-27 15:18:10 +00:00
fill_pathname_dir ( global - > name . savestate , global - > name . base ,
" .state " , sizeof ( global - > name . savestate ) ) ;
2015-07-01 17:30:34 +00:00
RARCH_LOG ( " %s \" %s \" . \n " ,
msg_hash_to_str ( MSG_REDIRECTING_SAVESTATE_TO ) ,
2015-07-27 15:18:10 +00:00
global - > name . savestate ) ;
2011-08-24 13:47:39 +00:00
}
2011-10-28 15:10:58 +00:00
2015-07-27 15:18:10 +00:00
if ( path_is_directory ( global - > name . cheatfile ) )
2014-12-15 20:55:51 +00:00
{
2015-07-27 15:18:10 +00:00
fill_pathname_dir ( global - > name . cheatfile , global - > name . base ,
" .state " , sizeof ( global - > name . cheatfile ) ) ;
2015-07-01 17:30:34 +00:00
RARCH_LOG ( " %s \" %s \" . \n " ,
msg_hash_to_str ( MSG_REDIRECTING_CHEATFILE_TO ) ,
2015-07-27 15:18:10 +00:00
global - > name . cheatfile ) ;
2014-12-15 20:55:51 +00:00
}
}
2015-04-13 09:37:38 +00:00
void rarch_set_paths ( const char * path )
2014-12-15 20:55:51 +00:00
{
2015-03-21 03:43:18 +00:00
global_t * global = global_get_ptr ( ) ;
2015-03-20 19:20:33 +00:00
2014-12-15 20:55:51 +00:00
set_basename ( path ) ;
2015-07-27 15:18:10 +00:00
if ( ! global - > has_set . save_path )
fill_pathname_noext ( global - > name . savefile , global - > name . base ,
" .srm " , sizeof ( global - > name . savefile ) ) ;
if ( ! global - > has_set . state_path )
fill_pathname_noext ( global - > name . savestate , global - > name . base ,
" .state " , sizeof ( global - > name . savestate ) ) ;
fill_pathname_noext ( global - > name . cheatfile , global - > name . base ,
" .cht " , sizeof ( global - > name . cheatfile ) ) ;
2014-12-15 20:55:51 +00:00
set_paths_redirect ( path ) ;
2011-08-24 13:47:39 +00:00
}
2015-06-28 15:02:01 +00:00
enum rarch_content_type rarch_path_is_media_type ( const char * path )
2015-06-23 05:25:48 +00:00
{
2015-07-01 17:30:34 +00:00
uint32_t hash_ext = msg_hash_calculate ( path_get_extension ( path ) ) ;
2015-06-23 05:25:48 +00:00
switch ( hash_ext )
{
2015-06-28 15:02:01 +00:00
# ifdef HAVE_FFMPEG
2015-06-23 05:25:48 +00:00
case MENU_VALUE_FILE_OGM :
case MENU_VALUE_FILE_MKV :
case MENU_VALUE_FILE_AVI :
case MENU_VALUE_FILE_MP4 :
case MENU_VALUE_FILE_FLV :
2015-06-23 06:32:21 +00:00
case MENU_VALUE_FILE_WEBM :
2015-06-23 05:25:48 +00:00
case MENU_VALUE_FILE_3GP :
case MENU_VALUE_FILE_F4F :
case MENU_VALUE_FILE_F4V :
2015-06-23 07:19:42 +00:00
case MENU_VALUE_FILE_MOV :
2015-06-23 07:25:56 +00:00
case MENU_VALUE_FILE_WMV :
2015-06-23 05:25:48 +00:00
return RARCH_CONTENT_MOVIE ;
case MENU_VALUE_FILE_MP3 :
case MENU_VALUE_FILE_M4A :
case MENU_VALUE_FILE_OGG :
case MENU_VALUE_FILE_FLAC :
case MENU_VALUE_FILE_WAV :
return RARCH_CONTENT_MUSIC ;
2015-06-28 15:02:01 +00:00
# endif
2015-06-28 16:55:00 +00:00
# ifdef HAVE_IMAGEVIEWER
2015-06-28 15:02:01 +00:00
case MENU_VALUE_FILE_JPG :
2015-06-28 16:10:48 +00:00
case MENU_VALUE_FILE_JPG_CAPS :
2015-06-28 15:02:01 +00:00
case MENU_VALUE_FILE_JPEG :
2015-06-28 16:10:48 +00:00
case MENU_VALUE_FILE_JPEG_CAPS :
2015-06-28 15:02:01 +00:00
case MENU_VALUE_FILE_PNG :
2015-06-28 16:10:48 +00:00
case MENU_VALUE_FILE_PNG_CAPS :
2015-06-28 15:02:01 +00:00
case MENU_VALUE_FILE_TGA :
case MENU_VALUE_FILE_BMP :
return RARCH_CONTENT_IMAGE ;
2015-06-28 16:55:00 +00:00
# endif
2015-06-28 17:15:12 +00:00
case 0 :
2015-06-23 05:25:48 +00:00
default :
break ;
}
return RARCH_CONTENT_NONE ;
}
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
# ifdef HAVE_NETPLAY
# 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
/**
* parse_input :
* @ argc : Count of ( commandline ) arguments .
2015-05-07 23:06:14 +00:00
* @ argv : ( Commandline ) arguments .
2015-01-11 01:21:18 +00:00
*
2015-06-30 13:26:14 +00:00
* Parses ( commandline ) arguments passed to program .
2015-01-11 01:21:18 +00:00
*
* */
2010-10-01 19:39:15 +00:00
static void parse_input ( int argc , char * argv [ ] )
2010-05-26 19:27:37 +00:00
{
2015-06-26 17:19:36 +00:00
const char * optstring = NULL ;
global_t * global = global_get_ptr ( ) ;
settings_t * settings = config_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
2015-06-12 14:27:39 +00:00
{ " libretro " , 1 , NULL , ' L ' } ,
2011-11-15 20:15:12 +00:00
# endif
2015-06-30 20:39:13 +00:00
{ " menu " , 0 , NULL , RA_OPT_MENU } ,
2015-06-12 14:27:39 +00:00
{ " help " , 0 , NULL , ' h ' } ,
{ " save " , 1 , NULL , ' s ' } ,
{ " fullscreen " , 0 , NULL , ' f ' } ,
{ " record " , 1 , NULL , ' r ' } ,
2015-06-30 20:39:13 +00:00
{ " recordconfig " , 1 , NULL , RA_OPT_RECORDCONFIG } ,
{ " size " , 1 , NULL , RA_OPT_SIZE } ,
2015-06-12 14:27:39 +00:00
{ " verbose " , 0 , NULL , ' v ' } ,
{ " config " , 1 , NULL , ' c ' } ,
2015-06-30 20:39:13 +00:00
{ " appendconfig " , 1 , NULL , RA_OPT_APPENDCONFIG } ,
2015-06-12 14:27:39 +00:00
{ " 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 ' } ,
2011-11-30 15:43:09 +00:00
# ifdef HAVE_NETPLAY
2015-06-12 14:27:39 +00:00
{ " host " , 0 , NULL , ' H ' } ,
{ " connect " , 1 , NULL , ' C ' } ,
{ " frames " , 1 , NULL , ' F ' } ,
2015-06-30 20:39:13 +00:00
{ " port " , 1 , NULL , RA_OPT_PORT } ,
{ " spectate " , 0 , NULL , RA_OPT_SPECTATE } ,
2012-06-01 13:15:06 +00:00
# endif
2015-06-30 20:39:13 +00:00
{ " nick " , 1 , NULL , RA_OPT_NICK } ,
2014-08-02 02:21:07 +00:00
# if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY)
2015-06-30 20:39:13 +00:00
{ " command " , 1 , NULL , RA_OPT_COMMAND } ,
2011-11-30 15:43:09 +00:00
# endif
2015-06-12 14:27:39 +00:00
{ " ups " , 1 , NULL , ' U ' } ,
2015-06-30 20:39:13 +00:00
{ " bps " , 1 , NULL , RA_OPT_BPS } ,
{ " ips " , 1 , NULL , RA_OPT_IPS } ,
{ " no-patch " , 0 , NULL , RA_OPT_NO_PATCH } ,
2015-06-12 14:27:39 +00:00
{ " detach " , 0 , NULL , ' D ' } ,
2015-06-30 20:39:13 +00:00
{ " features " , 0 , NULL , RA_OPT_FEATURES } ,
{ " subsystem " , 1 , NULL , RA_OPT_SUBSYSTEM } ,
{ " max-frames " , 1 , NULL , RA_OPT_MAX_FRAMES } ,
{ " eof-exit " , 0 , NULL , RA_OPT_EOF_EXIT } ,
{ " version " , 0 , NULL , RA_OPT_VERSION } ,
2015-06-12 15:31:28 +00:00
# ifdef HAVE_FILE_LOGGER
2015-06-30 20:39:13 +00:00
{ " log-file " , 1 , NULL , RA_OPT_LOG_FILE } ,
2015-06-12 15:31:28 +00:00
# endif
2010-10-01 19:39:15 +00:00
{ NULL , 0 , NULL , 0 }
} ;
2016-01-20 02:15:50 +00:00
current_core_type = CORE_TYPE_PLAIN ;
2015-06-30 21:06:07 +00:00
* global - > subsystem = ' \0 ' ;
2015-07-27 15:18:10 +00:00
global - > has_set . save_path = false ;
global - > has_set . state_path = false ;
global - > has_set . libretro = false ;
global - > has_set . libretro_directory = false ;
global - > has_set . verbosity = false ;
global - > has_set . netplay_mode = false ;
global - > has_set . username = false ;
global - > has_set . netplay_ip_address = false ;
global - > has_set . netplay_delay_frames = false ;
global - > has_set . netplay_ip_port = false ;
global - > has_set . ups_pref = false ;
global - > has_set . bps_pref = false ;
global - > has_set . ips_pref = false ;
global - > patch . ups_pref = false ;
global - > patch . bps_pref = false ;
global - > patch . ips_pref = false ;
* global - > name . ups = ' \0 ' ;
* global - > name . bps = ' \0 ' ;
* global - > name . ips = ' \0 ' ;
2011-11-30 15:43:09 +00:00
2015-12-10 20:43:44 +00:00
runloop_ctl ( RUNLOOP_CTL_UNSET_OVERRIDES_ACTIVE , NULL ) ;
2014-09-02 15:05:15 +00:00
2015-10-13 20:13:24 +00:00
if ( argc < 2 )
{
2016-01-20 02:15:50 +00:00
current_core_type = CORE_TYPE_DUMMY ;
2015-10-13 20:13:24 +00:00
return ;
}
2015-06-26 17:19:36 +00:00
/* Make sure we can call parse_input several times ... */
optind = 0 ;
optstring = " hs:fvS:A:c:U:DN:d: " BSV_MOVIE_ARG NETPLAY_ARG DYNAMIC_ARG FFMPEG_RECORD_ARG ;
2013-01-13 03:12:10 +00:00
2011-10-15 10:56:48 +00:00
for ( ; ; )
2010-05-29 13:21:30 +00:00
{
2015-03-20 19:20:33 +00:00
int port ;
2015-06-30 20:36:17 +00:00
int c = getopt_long ( argc , argv , optstring , opts , NULL ) ;
2015-06-26 18:35:02 +00:00
2010-10-01 19:39:15 +00:00
if ( c = = - 1 )
break ;
2015-06-30 20:39:13 +00:00
switch ( c )
2010-10-01 19:39:15 +00:00
{
case ' h ' :
2015-06-12 13:15:27 +00:00
print_help ( argv [ 0 ] ) ;
2010-10-01 19:39:15 +00:00
exit ( 0 ) ;
2014-04-12 11:22:24 +00:00
case ' d ' :
{
2014-08-31 23:37:44 +00:00
unsigned id = 0 ;
2014-04-12 11:22:24 +00:00
struct string_list * list = string_split ( optarg , " : " ) ;
2015-03-22 07:39:26 +00:00
port = 0 ;
2014-08-31 23:37:44 +00:00
if ( list & & list - > size = = 2 )
{
port = strtol ( list - > elems [ 0 ] . data , NULL , 0 ) ;
id = strtoul ( list - > elems [ 1 ] . data , NULL , 0 ) ;
}
2014-04-12 11:22:24 +00:00
string_list_free ( list ) ;
2011-01-10 15:53:37 +00:00
2015-01-05 00:58:00 +00:00
if ( port < 1 | | port > MAX_USERS )
2014-04-12 11:22:24 +00:00
{
RARCH_ERR ( " Connect device to a valid port. \n " ) ;
2015-06-12 13:15:27 +00:00
print_help ( argv [ 0 ] ) ;
2015-10-26 02:18:13 +00:00
retro_fail ( 1 , " parse_input() " ) ;
2014-04-12 11:22:24 +00:00
}
2015-03-20 19:20:33 +00:00
settings - > input . libretro_device [ port - 1 ] = id ;
2015-07-27 15:18:10 +00:00
global - > has_set . libretro_device [ port - 1 ] = true ;
2014-04-04 12:58:42 +00:00
break ;
2014-04-12 11:22:24 +00:00
}
2014-04-04 12:58:42 +00:00
2012-08-16 19:20:38 +00:00
case ' A ' :
port = strtol ( optarg , NULL , 0 ) ;
2015-01-05 00:58:00 +00:00
if ( port < 1 | | port > MAX_USERS )
2012-08-16 19:20:38 +00:00
{
RARCH_ERR ( " Connect dualanalog to a valid port. \n " ) ;
2015-06-12 13:15:27 +00:00
print_help ( argv [ 0 ] ) ;
2015-10-26 02:18:13 +00:00
retro_fail ( 1 , " parse_input() " ) ;
2012-08-16 19:20:38 +00:00
}
2015-03-20 19:20:33 +00:00
settings - > input . libretro_device [ port - 1 ] = RETRO_DEVICE_ANALOG ;
2015-07-27 15:18:10 +00:00
global - > has_set . libretro_device [ port - 1 ] = true ;
2012-08-16 19:20:38 +00:00
break ;
2010-10-01 19:39:15 +00:00
case ' s ' :
2015-07-27 15:18:10 +00:00
strlcpy ( global - > name . savefile , optarg ,
sizeof ( global - > name . savefile ) ) ;
global - > has_set . save_path = true ;
2011-01-08 18:15:18 +00:00
break ;
2011-07-09 06:37:08 +00:00
case ' f ' :
2015-11-30 21:02:54 +00:00
rarch_ctl ( RARCH_CTL_SET_FORCE_FULLSCREEN , NULL ) ;
2011-07-09 06:37:08 +00:00
break ;
2011-01-12 17:07:31 +00:00
case ' S ' :
2015-07-27 15:18:10 +00:00
strlcpy ( global - > name . savestate , optarg ,
sizeof ( global - > name . savestate ) ) ;
global - > has_set . state_path = true ;
2010-10-01 19:39:15 +00:00
break ;
2010-10-01 20:10:28 +00:00
case ' v ' :
2015-11-22 19:50:39 +00:00
{
bool * verbosity = retro_main_verbosity ( ) ;
if ( verbosity )
* verbosity = true ;
global - > has_set . verbosity = true ;
}
2010-10-01 20:10:28 +00:00
break ;
2011-06-19 09:11:04 +00:00
case ' N ' :
port = strtol ( optarg , NULL , 0 ) ;
2015-01-05 00:58:00 +00:00
if ( port < 1 | | port > MAX_USERS )
2011-06-19 09:11:04 +00:00
{
2012-08-16 19:20:38 +00:00
RARCH_ERR ( " Disconnect device from a valid port. \n " ) ;
2015-06-12 13:15:27 +00:00
print_help ( argv [ 0 ] ) ;
2015-10-26 02:18:13 +00:00
retro_fail ( 1 , " parse_input() " ) ;
2011-06-19 09:11:04 +00:00
}
2015-03-20 19:20:33 +00:00
settings - > input . libretro_device [ port - 1 ] = RETRO_DEVICE_NONE ;
2015-07-27 15:18:10 +00:00
global - > has_set . libretro_device [ port - 1 ] = true ;
2011-06-19 09:11:04 +00:00
break ;
2010-12-29 20:12:56 +00:00
case ' c ' :
2015-07-27 15:18:10 +00:00
strlcpy ( global - > path . config , optarg ,
sizeof ( global - > path . config ) ) ;
2010-12-29 20:12:56 +00:00
break ;
2011-01-05 19:07:55 +00:00
case ' r ' :
2015-03-21 03:43:18 +00:00
strlcpy ( global - > record . path , optarg ,
sizeof ( global - > record . path ) ) ;
2015-11-18 02:08:19 +00:00
{
bool * recording_enabled = recording_is_enabled ( ) ;
if ( recording_enabled )
* recording_enabled = true ;
}
2011-01-05 19:07:55 +00:00
break ;
2011-11-15 20:15:12 +00:00
# ifdef HAVE_DYNAMIC
case ' L ' :
2014-05-09 16:51:20 +00:00
if ( path_is_directory ( optarg ) )
{
2015-03-20 19:20:33 +00:00
* settings - > libretro = ' \0 ' ;
strlcpy ( settings - > libretro_directory , optarg ,
sizeof ( settings - > libretro_directory ) ) ;
2015-07-27 15:18:10 +00:00
global - > has_set . libretro = true ;
global - > has_set . libretro_directory = true ;
2014-06-16 19:50:29 +00:00
RARCH_WARN ( " Using old --libretro behavior. Setting libretro_directory to \" %s \" instead. \n " , optarg ) ;
2014-05-09 16:51:20 +00:00
}
else
{
2015-11-30 20:42:59 +00:00
runloop_ctl ( RUNLOOP_CTL_SET_LIBRETRO_PATH , optarg ) ;
2015-07-27 15:18:10 +00:00
global - > has_set . libretro = true ;
2014-05-09 16:51:20 +00:00
}
2011-11-15 20:15:12 +00:00
break ;
2014-09-02 15:05:15 +00:00
# endif
2011-02-02 11:10:27 +00:00
case ' P ' :
2011-11-20 19:19:05 +00:00
case ' R ' :
2015-12-01 00:38:45 +00:00
bsv_movie_set_start_path ( optarg ) ;
2015-12-01 00:25:36 +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 ) ;
if ( c = = ' R ' )
bsv_movie_ctl ( BSV_MOVIE_CTL_SET_START_RECORDING , NULL ) ;
else
bsv_movie_ctl ( BSV_MOVIE_CTL_UNSET_START_RECORDING , NULL ) ;
2011-11-18 17:03:24 +00:00
break ;
2011-11-20 19:19:05 +00:00
case ' M ' :
2016-01-20 03:07:24 +00:00
if ( string_is_equal ( optarg , " noload-nosave " ) )
2011-11-18 17:03:24 +00:00
{
2015-07-27 15:18:10 +00:00
global - > sram . load_disable = true ;
global - > sram . save_disable = true ;
2011-11-18 17:03:24 +00:00
}
2016-01-20 03:07:24 +00:00
else if ( string_is_equal ( optarg , " noload-save " ) )
2015-07-27 15:18:10 +00:00
global - > sram . load_disable = true ;
2016-01-20 03:07:24 +00:00
else if ( string_is_equal ( optarg , " load-nosave " ) )
2015-07-27 15:18:10 +00:00
global - > sram . save_disable = true ;
2016-01-20 03:07:24 +00:00
else if ( ! string_is_equal ( optarg , " load-save " ) )
2011-11-18 17:03:24 +00:00
{
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " Invalid argument in --sram-mode. \n " ) ;
2015-06-12 13:15:27 +00:00
print_help ( argv [ 0 ] ) ;
2015-10-26 02:18:13 +00:00
retro_fail ( 1 , " parse_input() " ) ;
2011-11-18 17:03:24 +00:00
}
2011-02-02 11:10:27 +00:00
break ;
2011-11-30 15:41:00 +00:00
# ifdef HAVE_NETPLAY
2011-02-13 15:40:24 +00:00
case ' H ' :
2015-07-27 15:18:10 +00:00
global - > has_set . netplay_ip_address = true ;
global - > netplay . enable = true ;
* global - > netplay . server = ' \0 ' ;
2011-02-13 15:40:24 +00:00
break ;
case ' C ' :
2015-07-27 15:18:10 +00:00
global - > has_set . netplay_ip_address = true ;
global - > netplay . enable = true ;
strlcpy ( global - > netplay . server , optarg ,
sizeof ( global - > netplay . server ) ) ;
2011-02-13 15:40:24 +00:00
break ;
2011-02-15 14:32:26 +00:00
case ' F ' :
2015-07-27 15:18:10 +00:00
global - > netplay . sync_frames = strtol ( optarg , NULL , 0 ) ;
global - > has_set . netplay_delay_frames = true ;
2011-02-15 14:32:26 +00:00
break ;
2011-11-30 15:41:00 +00:00
# endif
2011-02-15 14:32:26 +00:00
2015-06-30 20:43:41 +00:00
case RA_OPT_BPS :
2015-07-27 15:18:10 +00:00
strlcpy ( global - > name . bps , optarg ,
sizeof ( global - > name . bps ) ) ;
global - > patch . bps_pref = true ;
global - > has_set . bps_pref = true ;
2015-06-30 20:43:41 +00:00
break ;
2011-03-23 22:31:33 +00:00
case ' U ' :
2015-07-27 15:18:10 +00:00
strlcpy ( global - > name . ups , optarg ,
sizeof ( global - > name . ups ) ) ;
global - > patch . ups_pref = true ;
global - > has_set . ups_pref = true ;
2011-03-23 22:31:33 +00:00
break ;
2011-04-23 12:47:50 +00:00
2015-06-30 20:43:41 +00:00
case RA_OPT_IPS :
2015-07-27 15:18:10 +00:00
strlcpy ( global - > name . ips , optarg ,
sizeof ( global - > name . ips ) ) ;
global - > patch . ips_pref = true ;
global - > has_set . ips_pref = true ;
2015-06-30 20:43:41 +00:00
break ;
case RA_OPT_NO_PATCH :
2015-07-27 15:18:10 +00:00
global - > patch . block_patch = true ;
2015-06-30 20:43:41 +00:00
break ;
2011-04-23 12:47:50 +00:00
case ' D ' :
2012-01-05 12:30:13 +00:00
# if defined(_WIN32) && !defined(_XBOX)
2011-04-23 12:47:50 +00:00
FreeConsole ( ) ;
# endif
break ;
2015-10-20 00:43:21 +00:00
2015-06-30 20:36:17 +00:00
case RA_OPT_MENU :
2016-01-20 02:15:50 +00:00
current_core_type = CORE_TYPE_DUMMY ;
2015-06-30 20:36:17 +00:00
break ;
2013-04-14 14:24:19 +00:00
2011-11-30 15:41:00 +00:00
# ifdef HAVE_NETPLAY
2015-06-30 20:36:17 +00:00
case RA_OPT_PORT :
2015-07-27 15:18:10 +00:00
global - > has_set . netplay_ip_port = true ;
global - > netplay . port = strtoul ( optarg , NULL , 0 ) ;
2015-06-30 20:36:17 +00:00
break ;
2012-01-11 18:22:18 +00:00
2015-06-30 20:36:17 +00:00
case RA_OPT_SPECTATE :
2015-07-27 15:18:10 +00:00
global - > has_set . netplay_mode = true ;
global - > netplay . is_spectate = true ;
2015-06-30 20:36:17 +00:00
break ;
2012-01-21 17:12:42 +00:00
2014-08-01 03:04:59 +00:00
# endif
2015-06-30 20:36:17 +00:00
case RA_OPT_NICK :
2015-07-27 15:18:10 +00:00
global - > has_set . username = true ;
2015-06-30 20:36:17 +00:00
strlcpy ( settings - > username , optarg ,
sizeof ( settings - > username ) ) ;
break ;
2011-10-06 21:43:48 +00:00
2014-08-02 02:21:07 +00:00
# if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY)
2015-06-30 20:36:17 +00:00
case RA_OPT_COMMAND :
if ( network_cmd_send ( optarg ) )
exit ( 0 ) ;
else
2015-10-26 02:18:13 +00:00
retro_fail ( 1 , " network_cmd_send() " ) ;
2015-06-30 20:36:17 +00:00
break ;
2012-06-01 13:15:06 +00:00
# endif
2015-06-30 20:36:17 +00:00
case RA_OPT_APPENDCONFIG :
2015-07-27 15:18:10 +00:00
strlcpy ( global - > path . append_config , optarg ,
sizeof ( global - > path . append_config ) ) ;
2015-06-30 20:36:17 +00:00
break ;
case RA_OPT_SIZE :
{
if ( sscanf ( optarg , " %ux%u " , & global - > record . width ,
& global - > record . height ) ! = 2 )
{
RARCH_ERR ( " Wrong format for --size. \n " ) ;
print_help ( argv [ 0 ] ) ;
2015-10-26 02:18:13 +00:00
retro_fail ( 1 , " parse_input() " ) ;
2011-02-18 13:49:15 +00:00
}
break ;
2015-06-30 20:36:17 +00:00
}
2011-02-18 13:49:15 +00:00
2015-06-30 20:36:17 +00:00
case RA_OPT_RECORDCONFIG :
strlcpy ( global - > record . config , optarg ,
sizeof ( global - > record . config ) ) ;
break ;
case RA_OPT_MAX_FRAMES :
2015-09-26 11:28:33 +00:00
{
unsigned max_frames = strtoul ( optarg , NULL , 10 ) ;
2015-11-30 20:42:59 +00:00
runloop_ctl ( RUNLOOP_CTL_SET_MAX_FRAMES , & max_frames ) ;
2015-09-26 11:28:33 +00:00
}
2015-06-30 20:36:17 +00:00
break ;
case RA_OPT_SUBSYSTEM :
strlcpy ( global - > subsystem , optarg , sizeof ( global - > subsystem ) ) ;
break ;
case RA_OPT_FEATURES :
print_features ( ) ;
exit ( 0 ) ;
case RA_OPT_EOF_EXIT :
2015-12-01 00:29:16 +00:00
bsv_movie_ctl ( BSV_MOVIE_CTL_SET_END_EOF , NULL ) ;
2015-06-30 20:36:17 +00:00
break ;
case RA_OPT_VERSION :
print_version ( ) ;
exit ( 0 ) ;
2010-10-01 19:39:15 +00:00
2015-06-30 20:36:17 +00:00
# ifdef HAVE_FILE_LOGGER
case RA_OPT_LOG_FILE :
2015-11-23 14:45:02 +00:00
retro_main_log_file_init ( optarg ) ;
2015-06-30 20:36:17 +00:00
break ;
# endif
2015-06-30 20:39:13 +00:00
case ' ? ' :
print_help ( argv [ 0 ] ) ;
2015-10-26 02:18:13 +00:00
retro_fail ( 1 , " parse_input() " ) ;
2015-06-30 20:39:13 +00:00
2010-10-01 19:39:15 +00:00
default :
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " Error parsing arguments. \n " ) ;
2015-10-26 02:18:13 +00:00
retro_fail ( 1 , " parse_input() " ) ;
2010-10-01 19:39:15 +00:00
}
2010-05-29 13:21:30 +00:00
}
2016-01-19 22:44:32 +00:00
if ( rarch_ctl ( RARCH_CTL_IS_DUMMY_CORE , NULL ) )
2013-04-14 14:24:19 +00:00
{
if ( optind < argc )
{
2014-05-26 01:11:39 +00:00
RARCH_ERR ( " --menu was used, but content file was passed as well. \n " ) ;
2015-10-26 02:18:13 +00:00
retro_fail ( 1 , " parse_input() " ) ;
2013-04-14 14:24:19 +00:00
}
}
2015-03-21 03:43:18 +00:00
else if ( ! * global - > subsystem & & optind < argc )
2015-04-13 09:37:38 +00:00
rarch_set_paths ( argv [ optind ] ) ;
2015-03-21 03:43:18 +00:00
else if ( * global - > subsystem & & optind < argc )
2014-04-04 12:58:42 +00:00
set_special_paths ( argv + optind , argc - optind ) ;
2011-08-24 13:47:39 +00:00
else
2016-01-19 22:15:19 +00:00
content_ctl ( CONTENT_CTL_SET_DOES_NOT_NEED_CONTENT , NULL ) ;
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. */
2015-07-27 15:18:10 +00:00
if ( global - > has_set . save_path & &
path_is_directory ( global - > name . savefile ) )
strlcpy ( global - > dir . savefile , global - > name . savefile ,
sizeof ( global - > dir . savefile ) ) ;
if ( global - > has_set . state_path & &
path_is_directory ( global - > name . savestate ) )
strlcpy ( global - > dir . savestate , global - > name . savestate ,
sizeof ( global - > dir . savestate ) ) ;
2010-10-01 19:39:15 +00:00
}
2010-08-15 08:02:04 +00:00
2014-10-05 09:01:50 +00:00
static void rarch_init_savefile_paths ( void )
2011-01-12 20:57:55 +00:00
{
2015-06-25 11:17:42 +00:00
global_t * global = global_get_ptr ( ) ;
2015-12-10 21:30:25 +00:00
rarch_system_info_t * system = NULL ;
runloop_ctl ( RUNLOOP_CTL_SYSTEM_INFO_GET , & system ) ;
2015-03-21 03:43:18 +00:00
2016-01-22 14:34:43 +00:00
event_cmd_ctl ( EVENT_CMD_SAVEFILES_DEINIT , NULL ) ;
2014-10-03 10:26:29 +00:00
2015-03-21 03:43:18 +00:00
global - > savefiles = string_list_new ( ) ;
2015-10-26 02:18:13 +00:00
retro_assert ( global - > savefiles ) ;
2014-04-04 12:58:42 +00:00
2015-03-21 03:43:18 +00:00
if ( * global - > subsystem )
2011-01-12 20:57:55 +00:00
{
2014-09-02 01:21:33 +00:00
/* For subsystems, we know exactly which RAM types are supported. */
2014-08-02 09:48:42 +00:00
unsigned i , j ;
2015-05-07 23:06:14 +00:00
const struct retro_subsystem_info * info =
2014-12-15 17:50:04 +00:00
libretro_find_subsystem_info (
2015-06-25 11:17:42 +00:00
system - > special ,
system - > num_special ,
2015-03-21 03:43:18 +00:00
global - > subsystem ) ;
2012-01-06 19:32:30 +00:00
2014-08-20 15:18:43 +00:00
/* We'll handle this error gracefully later. */
2014-08-31 23:37:44 +00:00
unsigned num_content = min ( info ? info - > num_roms : 0 ,
2015-03-21 03:43:18 +00:00
global - > subsystem_fullpaths ?
global - > subsystem_fullpaths - > size : 0 ) ;
2014-04-04 15:04:01 +00:00
2015-07-27 15:18:10 +00:00
bool use_sram_dir = path_is_directory ( global - > dir . savefile ) ;
2012-01-06 19:32:30 +00:00
2014-07-28 17:47:12 +00:00
for ( i = 0 ; i < num_content ; i + + )
2014-04-04 12:58:42 +00:00
{
for ( j = 0 ; j < info - > roms [ i ] . num_memory ; j + + )
2012-01-06 19:32:30 +00:00
{
2014-04-04 12:58:42 +00:00
union string_list_elem_attr attr ;
2015-06-13 01:06:11 +00:00
char path [ PATH_MAX_LENGTH ] = { 0 } ;
char ext [ 32 ] = { 0 } ;
2014-08-31 23:37:44 +00:00
const struct retro_subsystem_memory_info * mem =
( const struct retro_subsystem_memory_info * )
& info - > roms [ i ] . memory [ j ] ;
2012-01-06 19:32:30 +00:00
2014-04-04 12:58:42 +00:00
snprintf ( ext , sizeof ( ext ) , " .%s " , mem - > extension ) ;
2012-01-06 19:32:30 +00:00
2014-04-04 12:58:42 +00:00
if ( use_sram_dir )
{
2014-08-20 15:18:43 +00:00
/* Redirect content fullpath to save directory. */
2015-07-27 15:18:10 +00:00
strlcpy ( path , global - > dir . savefile , sizeof ( path ) ) ;
2014-08-31 23:37:44 +00:00
fill_pathname_dir ( path ,
2015-03-21 03:43:18 +00:00
global - > subsystem_fullpaths - > elems [ i ] . data , ext ,
2014-04-04 12:58:42 +00:00
sizeof ( path ) ) ;
}
else
{
2015-03-21 03:43:18 +00:00
fill_pathname ( path , global - > subsystem_fullpaths - > elems [ i ] . data ,
2014-04-04 12:58:42 +00:00
ext , sizeof ( path ) ) ;
}
2012-01-06 19:32:30 +00:00
2014-04-04 12:58:42 +00:00
attr . i = mem - > type ;
2015-03-21 03:43:18 +00:00
string_list_append ( global - > savefiles , path , attr ) ;
2012-01-06 19:32:30 +00:00
}
2014-04-04 12:58:42 +00:00
}
2012-01-06 19:32:30 +00:00
2014-08-20 15:18:43 +00:00
/* Let other relevant paths be inferred from the main SRAM location. */
2015-07-27 15:18:10 +00:00
if ( ! global - > has_set . save_path )
fill_pathname_noext ( global - > name . savefile , global - > name . base , " .srm " ,
sizeof ( global - > name . savefile ) ) ;
if ( path_is_directory ( global - > name . savefile ) )
2014-04-04 12:58:42 +00:00
{
2015-07-27 15:18:10 +00:00
fill_pathname_dir ( global - > name . savefile , global - > name . base , " .srm " ,
sizeof ( global - > name . savefile ) ) ;
2015-07-01 17:30:34 +00:00
RARCH_LOG ( " %s \" %s \" . \n " ,
msg_hash_to_str ( MSG_REDIRECTING_SAVEFILE_TO ) ,
2015-07-27 15:18:10 +00:00
global - > name . savefile ) ;
2014-04-04 12:58:42 +00:00
}
}
else
{
union string_list_elem_attr attr ;
2015-06-12 15:00:37 +00:00
char savefile_name_rtc [ PATH_MAX_LENGTH ] = { 0 } ;
2014-08-02 23:54:10 +00:00
2014-04-04 12:58:42 +00:00
attr . i = RETRO_MEMORY_SAVE_RAM ;
2015-07-27 15:18:10 +00:00
string_list_append ( global - > savefiles , global - > name . savefile , attr ) ;
2011-02-11 13:27:19 +00:00
2014-08-20 15:18:43 +00:00
/* Infer .rtc save path from save ram path. */
2014-04-04 12:58:42 +00:00
attr . i = RETRO_MEMORY_RTC ;
fill_pathname ( savefile_name_rtc ,
2015-07-27 15:18:10 +00:00
global - > name . savefile , " .rtc " , sizeof ( savefile_name_rtc ) ) ;
2015-03-21 03:43:18 +00:00
string_list_append ( global - > savefiles , savefile_name_rtc , attr ) ;
2011-01-12 20:57:55 +00:00
}
2014-10-05 09:01:50 +00:00
}
2011-02-11 13:27:19 +00:00
2015-03-22 06:28:45 +00:00
static bool init_state ( void )
2011-08-26 15:32:04 +00:00
{
2015-11-29 20:38:47 +00:00
video_driver_ctl ( RARCH_DISPLAY_CTL_SET_ACTIVE , NULL ) ;
2015-11-29 20:34:45 +00:00
audio_driver_ctl ( RARCH_AUDIO_CTL_SET_ACTIVE , NULL ) ;
2015-03-22 06:28:45 +00:00
2015-12-04 02:20:33 +00:00
rarch_ctl ( RARCH_CTL_UNSET_FORCE_FULLSCREEN , NULL ) ;
2015-11-30 21:02:54 +00:00
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
2014-10-05 17:13:03 +00:00
2015-01-11 01:21:18 +00:00
/**
* rarch_main_init :
* @ 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
*
* Returns : 0 on success , otherwise 1 if there was an error .
* */
2012-04-21 21:25:32 +00:00
int rarch_main_init ( int argc , char * argv [ ] )
2012-01-14 15:08:54 +00:00
{
2014-08-02 09:48:42 +00:00
int sjlj_ret ;
2015-11-30 18:30:05 +00:00
bool * verbosity = NULL ;
2014-08-02 09:48:42 +00:00
2012-01-14 15:08:54 +00:00
init_state ( ) ;
2011-12-25 20:39:58 +00:00
2015-11-30 18:30:05 +00:00
if ( ( sjlj_ret = setjmp ( error_sjlj_context ) ) > 0 )
2012-01-14 15:08:54 +00:00
{
2015-11-30 18:30:05 +00:00
RARCH_ERR ( " Fatal error received in: \" %s \" \n " , error_string ) ;
2012-01-14 15:08:54 +00:00
return sjlj_ret ;
}
2015-11-30 18:30:05 +00:00
2015-12-04 08:06:47 +00:00
rarch_ctl ( RARCH_CTL_SET_ERROR_ON_INIT , NULL ) ;
2015-11-23 14:45:02 +00:00
retro_main_log_file_init ( NULL ) ;
2012-05-03 22:14:42 +00:00
parse_input ( argc , argv ) ;
2015-11-22 19:50:39 +00:00
verbosity = retro_main_verbosity ( ) ;
if ( verbosity & & * verbosity )
2011-12-25 20:39:58 +00:00
{
2015-05-19 17:55:21 +00:00
char str [ PATH_MAX_LENGTH ] = { 0 } ;
2015-04-16 18:17:05 +00:00
2012-10-16 11:57:35 +00:00
RARCH_LOG_OUTPUT ( " === Build ======================================= " ) ;
2015-05-13 11:21:43 +00:00
rarch_info_get_capabilities ( RARCH_CAPABILITIES_CPU , str , sizeof ( str ) ) ;
2015-04-16 18:19:53 +00:00
fprintf ( stderr , " %s " , str ) ;
2015-04-16 18:17:05 +00:00
fprintf ( stderr , " Built: %s \n " , __DATE__ ) ;
2014-01-11 17:51:42 +00:00
RARCH_LOG_OUTPUT ( " Version: %s \n " , PACKAGE_VERSION ) ;
# ifdef HAVE_GIT_VERSION
RARCH_LOG_OUTPUT ( " Git: %s \n " , rarch_git_version ) ;
# endif
2012-10-16 11:57:35 +00:00
RARCH_LOG_OUTPUT ( " ================================================= \n " ) ;
2011-12-25 20:39:58 +00:00
}
2015-11-30 20:28:55 +00:00
rarch_ctl ( RARCH_CTL_VALIDATE_CPU_FEATURES , NULL ) ;
2012-01-28 14:47:02 +00:00
config_load ( ) ;
2015-11-24 19:44:45 +00:00
rarch_task_init ( ) ;
2010-12-30 12:54:49 +00:00
2015-06-23 05:55:02 +00:00
{
settings_t * settings = config_get_ptr ( ) ;
2015-06-28 15:21:32 +00:00
if ( settings & & ( settings - > multimedia . builtin_mediaplayer_enable | |
settings - > multimedia . builtin_imageviewer_enable ) )
2015-06-23 05:55:02 +00:00
{
2016-01-20 02:44:01 +00:00
char * fullpath = NULL ;
# if defined(HAVE_FFMPEG) || defined(HAVE_IMAGEVIEWER)
global_t * global = global_get_ptr ( ) ;
# endif
2015-11-30 20:42:59 +00:00
runloop_ctl ( RUNLOOP_CTL_GET_CONTENT_PATH , & fullpath ) ;
2015-11-18 10:43:25 +00:00
switch ( rarch_path_is_media_type ( fullpath ) )
2015-06-23 05:55:02 +00:00
{
case RARCH_CONTENT_MOVIE :
case RARCH_CONTENT_MUSIC :
2015-06-28 15:21:32 +00:00
if ( settings - > multimedia . builtin_mediaplayer_enable )
{
# ifdef HAVE_FFMPEG
2016-01-20 02:15:50 +00:00
global - > has_set . libretro = false ;
current_core_type = CORE_TYPE_FFMPEG ;
2015-06-28 15:21:32 +00:00
# endif
}
2015-06-23 05:55:02 +00:00
break ;
2015-06-28 16:55:00 +00:00
# ifdef HAVE_IMAGEVIEWER
2015-06-28 15:02:01 +00:00
case RARCH_CONTENT_IMAGE :
2015-06-28 15:21:32 +00:00
if ( settings - > multimedia . builtin_imageviewer_enable )
{
2016-01-20 02:15:50 +00:00
global - > has_set . libretro = false ;
current_core_type = CORE_TYPE_IMAGEVIEWER ;
2015-06-28 15:21:32 +00:00
}
2015-06-28 15:02:01 +00:00
break ;
2015-06-28 16:55:00 +00:00
# endif
2015-06-23 05:55:02 +00:00
default :
break ;
}
}
}
2016-01-20 02:15:50 +00:00
init_libretro_sym ( current_core_type ) ;
2015-12-07 12:56:33 +00:00
runloop_ctl ( RUNLOOP_CTL_SYSTEM_INFO_INIT , NULL ) ;
2015-12-11 09:52:15 +00:00
driver_ctl ( RARCH_DRIVER_CTL_INIT_PRE , NULL ) ;
2016-01-22 14:34:43 +00:00
if ( ! event_cmd_ctl ( EVENT_CMD_CORE_INIT , NULL ) )
goto error ;
2010-10-01 19:39:15 +00:00
2016-01-22 14:34:43 +00:00
event_cmd_ctl ( EVENT_CMD_DRIVERS_INIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_COMMAND_INIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_REMOTE_INIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_REWIND_INIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_CONTROLLERS_INIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_RECORD_INIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_CHEATS_INIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_REMAPPING_INIT , NULL ) ;
2011-01-23 01:23:20 +00:00
2016-01-22 14:34:43 +00:00
event_cmd_ctl ( EVENT_CMD_SAVEFILES_INIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_SET_PER_GAME_RESOLUTION , NULL ) ;
2014-10-13 05:35:18 +00:00
2015-12-04 08:06:47 +00:00
rarch_ctl ( RARCH_CTL_UNSET_ERROR_ON_INIT , NULL ) ;
2016-01-19 22:26:47 +00:00
rarch_ctl ( RARCH_CTL_SET_INITED , NULL ) ;
2012-01-14 13:08:43 +00:00
return 0 ;
2011-08-13 02:09:08 +00:00
2012-01-14 13:08:43 +00:00
error :
2016-01-22 14:34:43 +00:00
event_cmd_ctl ( EVENT_CMD_CORE_DEINIT , NULL ) ;
2016-01-19 22:26:47 +00:00
rarch_ctl ( RARCH_CTL_UNSET_INITED , NULL ) ;
2012-01-14 13:08:43 +00:00
return 1 ;
}
2015-09-27 00:16:24 +00:00
# define FAIL_CPU(simd_type) do { \
RARCH_ERR ( simd_type " code is compiled in, but CPU does not support this feature. Cannot continue. \n " ) ; \
2015-10-26 02:18:13 +00:00
retro_fail ( 1 , " validate_cpu_features() " ) ; \
2015-09-27 00:16:24 +00:00
} while ( 0 )
2015-09-27 00:04:53 +00:00
bool rarch_ctl ( enum rarch_ctl_state state , void * data )
2014-09-03 16:16:49 +00:00
{
2016-01-19 22:26:47 +00:00
static bool rarch_is_inited = false ;
2015-12-04 08:07:21 +00:00
static bool rarch_error_on_init = false ;
2015-12-04 02:20:33 +00:00
static bool rarch_block_config_read = false ;
static bool rarch_force_fullscreen = false ;
global_t * global = global_get_ptr ( ) ;
settings_t * settings = config_get_ptr ( ) ;
2015-03-18 05:47:22 +00:00
2015-09-26 23:58:24 +00:00
switch ( state )
2014-09-03 16:16:49 +00:00
{
2016-01-22 14:43:40 +00:00
case RARCH_CTL_INIT_SYSTEM_AV_INFO :
{
struct retro_system_av_info * av_info = video_viewport_get_system_av_info ( ) ;
core . retro_get_system_av_info ( av_info ) ;
runloop_ctl ( RUNLOOP_CTL_SET_FRAME_LIMIT , NULL ) ;
}
break ;
2016-01-20 02:10:52 +00:00
case RARCH_CTL_IS_PLAIN_CORE :
2016-01-20 02:15:50 +00:00
return ( current_core_type = = CORE_TYPE_PLAIN ) ;
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-01-19 22:26:47 +00:00
case RARCH_CTL_IS_INITED :
return rarch_is_inited ;
case RARCH_CTL_UNSET_INITED :
rarch_is_inited = false ;
break ;
case RARCH_CTL_SET_INITED :
rarch_is_inited = true ;
break ;
2015-12-07 14:03:54 +00:00
case RARCH_CTL_DESTROY :
2016-01-19 22:26:47 +00:00
rarch_is_inited = false ;
2015-12-07 14:03:54 +00:00
rarch_error_on_init = false ;
rarch_block_config_read = false ;
rarch_force_fullscreen = false ;
runloop_ctl ( RUNLOOP_CTL_MSG_QUEUE_DEINIT , NULL ) ;
2016-01-22 14:34:43 +00:00
event_cmd_ctl ( EVENT_CMD_DRIVERS_DEINIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_LOG_FILE_DEINIT , NULL ) ;
2015-12-07 14:03:54 +00:00
runloop_ctl ( RUNLOOP_CTL_STATE_FREE , NULL ) ;
runloop_ctl ( RUNLOOP_CTL_GLOBAL_FREE , NULL ) ;
runloop_ctl ( RUNLOOP_CTL_DATA_DEINIT , NULL ) ;
config_free ( ) ;
return true ;
2015-12-07 13:59:09 +00:00
case RARCH_CTL_DEINIT :
{
bool inited = false ;
if ( ! global )
return false ;
2016-01-19 22:26:47 +00:00
inited = rarch_ctl ( RARCH_CTL_IS_INITED , NULL ) ;
2015-12-07 13:59:09 +00:00
if ( ! inited )
return false ;
2016-01-22 14:34:43 +00:00
event_cmd_ctl ( EVENT_CMD_DRIVERS_DEINIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_DRIVERS_INIT , NULL ) ;
2015-12-07 13:59:09 +00:00
}
return true ;
2015-12-07 14:01:53 +00:00
case RARCH_CTL_PREINIT :
if ( ! config_realloc ( ) )
return false ;
2016-01-22 14:34:43 +00:00
event_cmd_ctl ( EVENT_CMD_HISTORY_DEINIT , NULL ) ;
2015-12-07 14:01:53 +00:00
runloop_ctl ( RUNLOOP_CTL_CLEAR_STATE , NULL ) ;
return true ;
2015-12-07 13:59:09 +00:00
case RARCH_CTL_INIT :
rarch_ctl ( RARCH_CTL_DEINIT , NULL ) ;
init_state ( ) ;
{
unsigned i ;
for ( i = 0 ; i < MAX_USERS ; i + + )
settings - > input . libretro_device [ i ] = RETRO_DEVICE_JOYPAD ;
}
runloop_ctl ( RUNLOOP_CTL_MSG_QUEUE_INIT , NULL ) ;
return true ;
2015-12-07 13:30:36 +00:00
case RARCH_CTL_SET_PATHS_REDIRECT :
set_paths_redirect ( global - > name . base ) ;
break ;
2015-12-04 08:06:47 +00:00
case RARCH_CTL_SET_ERROR_ON_INIT :
rarch_error_on_init = true ;
break ;
case RARCH_CTL_UNSET_ERROR_ON_INIT :
rarch_error_on_init = false ;
break ;
case RARCH_CTL_IS_ERROR_ON_INIT :
return rarch_error_on_init ;
2015-11-30 21:02:54 +00:00
case RARCH_CTL_SET_FORCE_FULLSCREEN :
rarch_force_fullscreen = true ;
break ;
2015-12-04 02:20:33 +00:00
case RARCH_CTL_UNSET_FORCE_FULLSCREEN :
rarch_force_fullscreen = false ;
break ;
2015-11-30 21:02:54 +00:00
case RARCH_CTL_IS_FORCE_FULLSCREEN :
return rarch_force_fullscreen ;
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 ;
2015-11-30 20:28:55 +00:00
case RARCH_CTL_REPLACE_CONFIG :
2015-09-27 00:04:53 +00:00
{
char * path = ( char * ) data ;
if ( ! path )
return false ;
/* If config file to be replaced is the same as the
* current config file , exit . */
2016-01-20 03:07:24 +00:00
if ( string_is_equal ( path , global - > path . config ) )
2015-09-27 00:04:53 +00:00
return false ;
if ( settings - > config_save_on_exit & & * global - > path . config )
config_save_file ( global - > path . config ) ;
strlcpy ( global - > path . config , path , sizeof ( global - > path . config ) ) ;
2015-11-30 21:09:28 +00:00
rarch_ctl ( RARCH_CTL_UNSET_BLOCK_CONFIG_READ , NULL ) ;
2015-09-27 00:04:53 +00:00
* settings - > libretro = ' \0 ' ; /* Load core in new config. */
}
2015-11-30 20:42:59 +00:00
runloop_ctl ( RUNLOOP_CTL_PREPARE_DUMMY , NULL ) ;
2015-09-27 00:04:53 +00:00
return true ;
2015-11-30 20:28:55 +00:00
case RARCH_CTL_MENU_RUNNING :
2014-10-03 17:19:52 +00:00
# ifdef HAVE_MENU
2015-12-06 16:41:00 +00:00
menu_driver_ctl ( RARCH_MENU_CTL_SET_TOGGLE , NULL ) ;
2015-07-16 09:57:50 +00:00
# endif
# ifdef HAVE_OVERLAY
if ( settings - > input . overlay_hide_in_menu )
2016-01-22 14:34:43 +00:00
event_cmd_ctl ( EVENT_CMD_OVERLAY_DEINIT , NULL ) ;
2014-10-03 17:19:52 +00:00
# endif
2014-09-03 16:36:46 +00:00
break ;
2015-11-30 20:28:55 +00:00
case RARCH_CTL_LOAD_CONTENT :
case RARCH_CTL_LOAD_CONTENT_FFMPEG :
case RARCH_CTL_LOAD_CONTENT_IMAGEVIEWER :
2015-06-28 15:21:32 +00:00
# ifdef HAVE_MENU
/* If content loading fails, we go back to menu. */
2016-01-25 04:31:21 +00:00
if ( ! menu_content_load ( ) )
2015-11-30 20:28:55 +00:00
rarch_ctl ( RARCH_CTL_MENU_RUNNING , NULL ) ;
2015-06-28 15:21:32 +00:00
# endif
2015-12-05 06:53:02 +00:00
frontend_driver_content_loaded ( ) ;
2015-06-28 15:21:32 +00:00
break ;
2015-11-30 20:28:55 +00:00
case RARCH_CTL_MENU_RUNNING_FINISHED :
2014-10-03 17:19:52 +00:00
# ifdef HAVE_MENU
2015-12-06 16:41:00 +00:00
menu_driver_ctl ( RARCH_MENU_CTL_UNSET_TOGGLE , NULL ) ;
2014-10-03 17:19:52 +00:00
# endif
2015-03-22 17:59:16 +00:00
video_driver_set_texture_enable ( false , false ) ;
2015-07-16 09:57:50 +00:00
# ifdef HAVE_OVERLAY
2015-07-18 13:07:16 +00:00
if ( settings & & settings - > input . overlay_hide_in_menu )
2016-01-22 14:34:43 +00:00
event_cmd_ctl ( EVENT_CMD_OVERLAY_INIT , NULL ) ;
2015-07-16 09:57:50 +00:00
# endif
2014-09-03 16:36:46 +00:00
break ;
2015-11-30 20:28:55 +00:00
case RARCH_CTL_QUIT :
2015-12-04 11:44:12 +00:00
runloop_ctl ( RUNLOOP_CTL_SET_SHUTDOWN , NULL ) ;
2015-11-30 20:28:55 +00:00
rarch_ctl ( RARCH_CTL_MENU_RUNNING_FINISHED , NULL ) ;
2014-09-03 16:16:49 +00:00
break ;
2015-11-30 20:28:55 +00:00
case RARCH_CTL_FORCE_QUIT :
rarch_ctl ( RARCH_CTL_QUIT , NULL ) ;
2014-09-12 03:14:43 +00:00
break ;
2015-11-30 20:28:55 +00:00
case RARCH_CTL_VALIDATE_CPU_FEATURES :
2015-09-27 00:16:24 +00:00
{
uint64_t cpu = retro_get_cpu_features ( ) ;
( void ) cpu ;
# 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
}
break ;
2015-11-30 20:28:55 +00:00
case RARCH_CTL_VERIFY_API_VERSION :
2015-10-06 17:34:09 +00:00
RARCH_LOG ( " Version of libretro API: %u \n " , core . retro_api_version ( ) ) ;
2015-09-27 00:06:58 +00:00
RARCH_LOG ( " Compiled against API: %u \n " , RETRO_API_VERSION ) ;
2015-10-06 17:34:09 +00:00
if ( core . retro_api_version ( ) ! = RETRO_API_VERSION )
2015-09-27 00:06:58 +00:00
RARCH_WARN ( " %s \n " , msg_hash_to_str ( MSG_LIBRETRO_ABI_BREAK ) ) ;
break ;
2015-11-30 20:28:55 +00:00
case RARCH_CTL_FILL_PATHNAMES :
2015-09-27 00:18:45 +00:00
rarch_init_savefile_paths ( ) ;
2015-12-01 00:38:45 +00:00
bsv_movie_set_path ( global - > name . savefile ) ;
2015-09-27 00:18:45 +00:00
if ( ! * global - > name . base )
return false ;
if ( ! * global - > name . ups )
fill_pathname_noext ( global - > name . ups , global - > name . base , " .ups " ,
sizeof ( global - > name . ups ) ) ;
if ( ! * global - > name . bps )
fill_pathname_noext ( global - > name . bps , global - > name . base , " .bps " ,
sizeof ( global - > name . bps ) ) ;
if ( ! * global - > name . ips )
fill_pathname_noext ( global - > name . ips , global - > name . base , " .ips " ,
sizeof ( global - > name . ips ) ) ;
break ;
2015-11-30 20:28:55 +00:00
case RARCH_CTL_NONE :
2014-09-03 16:16:49 +00:00
default :
2015-09-27 00:04:53 +00:00
return false ;
2014-09-03 16:16:49 +00:00
}
2015-09-27 00:04:53 +00:00
return true ;
2014-09-03 16:16:49 +00:00
}
2015-01-11 01:21:18 +00:00
/**
* rarch_main_deinit :
*
2015-06-30 13:26:14 +00:00
* Deinitializes the program .
2015-01-11 01:21:18 +00:00
* */
2012-04-21 21:25:32 +00:00
void rarch_main_deinit ( void )
2012-01-14 13:08:43 +00:00
{
2015-03-21 03:43:18 +00:00
global_t * global = global_get_ptr ( ) ;
2016-01-22 14:34:43 +00:00
event_cmd_ctl ( EVENT_CMD_NETPLAY_DEINIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_COMMAND_DEINIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_REMOTE_DEINIT , NULL ) ;
2011-02-13 16:45:14 +00:00
2015-07-27 15:18:10 +00:00
if ( global - > sram . use )
2016-01-22 14:34:43 +00:00
event_cmd_ctl ( EVENT_CMD_AUTOSAVE_DEINIT , NULL ) ;
2015-03-15 05:50:08 +00:00
2016-01-22 14:34:43 +00:00
event_cmd_ctl ( EVENT_CMD_RECORD_DEINIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_SAVEFILES , NULL ) ;
2011-02-25 10:47:27 +00:00
2016-01-22 14:34:43 +00:00
event_cmd_ctl ( EVENT_CMD_REWIND_DEINIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_CHEATS_DEINIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_BSV_MOVIE_DEINIT , NULL ) ;
2015-03-15 05:50:08 +00:00
2016-01-22 14:34:43 +00:00
event_cmd_ctl ( EVENT_CMD_AUTOSAVE_STATE , NULL ) ;
2012-06-02 19:33:37 +00:00
2016-01-22 14:34:43 +00:00
event_cmd_ctl ( EVENT_CMD_CORE_DEINIT , NULL ) ;
2013-01-05 22:44:49 +00:00
2016-01-22 14:34:43 +00:00
event_cmd_ctl ( EVENT_CMD_TEMPORARY_CONTENT_DEINIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_SUBSYSTEM_FULLPATHS_DEINIT , NULL ) ;
event_cmd_ctl ( EVENT_CMD_SAVEFILES_DEINIT , NULL ) ;
2013-01-21 22:51:56 +00:00
2016-01-19 22:26:47 +00:00
rarch_ctl ( RARCH_CTL_UNSET_INITED , NULL ) ;
2012-01-14 13:08:43 +00:00
}
2015-01-09 17:48:03 +00:00
2015-11-28 19:11:55 +00:00
int rarch_info_get_capabilities ( enum rarch_capabilities type , char * s , size_t len )
{
switch ( type )
{
case RARCH_CAPABILITIES_CPU :
{
uint64_t cpu = retro_get_cpu_features ( ) ;
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 ) ;
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 ) ;
}
break ;
case RARCH_CAPABILITIES_COMPILER :
# if defined(_MSC_VER)
snprintf ( s , len , " Compiler: MSVC (%d) %u-bit " , _MSC_VER , ( unsigned )
( CHAR_BIT * sizeof ( size_t ) ) ) ;
# elif defined(__SNC__)
snprintf ( s , len , " Compiler: SNC (%d) %u-bit " ,
__SN_VER__ , ( unsigned ) ( CHAR_BIT * sizeof ( size_t ) ) ) ;
# elif defined(_WIN32) && defined(__GNUC__)
snprintf ( s , len , " Compiler: MinGW (%d.%d.%d) %u-bit " ,
__GNUC__ , __GNUC_MINOR__ , __GNUC_PATCHLEVEL__ , ( unsigned )
( CHAR_BIT * sizeof ( size_t ) ) ) ;
# elif defined(__clang__)
snprintf ( s , len , " Compiler: Clang/LLVM (%s) %u-bit " ,
__clang_version__ , ( unsigned ) ( CHAR_BIT * sizeof ( size_t ) ) ) ;
# elif defined(__GNUC__)
snprintf ( s , len , " Compiler: GCC (%d.%d.%d) %u-bit " ,
__GNUC__ , __GNUC_MINOR__ , __GNUC_PATCHLEVEL__ , ( unsigned )
( CHAR_BIT * sizeof ( size_t ) ) ) ;
# else
snprintf ( s , len , " Unknown compiler %u-bit " ,
( unsigned ) ( CHAR_BIT * sizeof ( size_t ) ) ) ;
# endif
break ;
default :
case RARCH_CAPABILITIES_NONE :
break ;
}
return 0 ;
}
2015-11-29 01:27:48 +00:00
/**
* retro_fail :
* @ error_code : Error code .
* @ error : Error message to show .
*
* Sanely kills the program .
* */
void retro_fail ( int error_code , const char * error )
{
/* We cannot longjmp unless we're in rarch_main_init().
* If not , something went very wrong , and we should
* just exit right away . */
2015-12-04 08:06:47 +00:00
retro_assert ( rarch_ctl ( RARCH_CTL_IS_ERROR_ON_INIT , NULL ) ) ;
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
}