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
2015-01-07 16:46:50 +00:00
* Copyright ( C ) 2011 - 2015 - Daniel De Matteis
* 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>
2014-10-22 02:27:51 +00:00
# include <boolean.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-07-01 17:30:34 +00:00
# include "msg_hash.h"
2015-06-14 14:45:20 +00:00
2015-01-13 01:29:08 +00:00
# include "libretro_version_1.h"
2014-10-22 02:27:51 +00:00
# include "dynamic.h"
2015-04-07 01:22:33 +00:00
# include "configuration.h"
2010-12-24 00:26:36 +00:00
# include "general.h"
2015-01-09 16:40:47 +00:00
# include "retroarch.h"
2015-03-24 12:45:53 +00:00
# include "runloop_data.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-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
2014-07-22 01:12:56 +00:00
# ifdef HAVE_MENU
2015-01-10 03:53:37 +00:00
# include "menu/menu.h"
2015-06-14 14:45:20 +00:00
# include "menu/menu_hash.h"
2015-06-16 01:03:20 +00:00
# include "menu/menu_entries.h"
2015-05-14 22:22:26 +00:00
# include "menu/menu_setting.h"
2014-10-28 18:54:23 +00:00
# include "menu/menu_shader.h"
2015-01-11 05:24:44 +00:00
# include "menu/menu_input.h"
2014-07-22 01:12:56 +00:00
# endif
2015-06-21 22:29:28 +00:00
char orig_savestate_dir [ PATH_MAX_LENGTH ] ;
char orig_savefile_dir [ PATH_MAX_LENGTH ] ;
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 . */
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
} ;
2011-01-25 12:03:53 +00:00
# include "config.features.h"
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")
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-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-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-07-27 15:18:10 +00:00
strlcpy ( global - > path . fullpath , path , sizeof ( global - > path . fullpath ) ) ;
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 ( ) ;
rarch_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-07-16 06:45:49 +00:00
if ( ! settings - > system_directory | | settings - > system_directory [ 0 ] = = ' \0 ' )
{
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-07-26 21:23:41 +00:00
2014-04-04 12:58:42 +00:00
}
2015-05-07 23:06:14 +00:00
void set_paths_redirect ( const char * path )
2011-08-24 13:47:39 +00:00
{
2015-06-14 14:45:20 +00:00
global_t * global = global_get_ptr ( ) ;
settings_t * settings = config_get_ptr ( ) ;
2015-06-25 10:36:55 +00:00
rarch_system_info_t * info = rarch_system_info_get_ptr ( ) ;
2015-06-25 08:51:05 +00:00
2015-06-25 10:36:55 +00:00
uint32_t global_library_name_hash = ( ( global & & info - > info . library_name & &
( info - > info . library_name [ 0 ] ! = ' \0 ' ) )
2015-07-01 17:30:34 +00:00
? msg_hash_calculate ( info - > info . library_name ) : 0 ) ;
2015-05-07 23:06:14 +00:00
2015-06-14 14:45:20 +00:00
if (
global_library_name_hash ! = 0 & &
( global_library_name_hash ! = MENU_VALUE_NO_CORE ) )
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-07-27 15:18:10 +00:00
if ( settings - > sort_savefiles_enable & & global - > dir . savefile [ 0 ] ! = ' \0 ' )
2015-06-14 14:45:20 +00:00
{
2015-07-27 15:18:10 +00:00
strlcpy ( orig_savefile_dir , global - > dir . savefile ,
sizeof ( orig_savefile_dir ) ) ;
2015-06-14 14:45:20 +00:00
fill_pathname_dir (
2015-07-27 15:18:10 +00:00
global - > dir . savefile ,
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-07-27 15:18:10 +00:00
if ( ! path_is_directory ( global - > dir . savefile ) & & global - > dir . savestate [ 0 ] ! = ' \0 ' )
if ( ! path_mkdir ( global - > dir . savefile ) )
strlcpy ( global - > dir . savefile ,
2015-06-14 14:45:20 +00:00
orig_savefile_dir ,
2015-07-27 15:18:10 +00:00
sizeof ( global - > dir . savefile ) ) ;
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-07-27 15:18:10 +00:00
if ( settings - > sort_savestates_enable & & global - > dir . savefile [ 0 ] ! = ' \0 ' )
2015-06-14 14:45:20 +00:00
{
strlcpy ( orig_savestate_dir ,
2015-07-27 15:18:10 +00:00
global - > dir . savestate ,
sizeof ( orig_savestate_dir ) ) ;
fill_pathname_dir ( global - > dir . savestate ,
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-07-27 15:18:10 +00:00
if ( ! path_is_directory ( global - > dir . savestate ) )
if ( ! path_mkdir ( global - > dir . savestate ) )
strlcpy ( global - > dir . savestate ,
2015-06-14 14:45:20 +00:00
orig_savestate_dir ,
2015-07-27 15:18:10 +00:00
sizeof ( global - > dir . savestate ) ) ;
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-07-27 15:18:10 +00:00
if ( path_is_directory ( global - > dir . savefile ) )
strlcpy ( global - > name . savefile , global - > dir . savefile ,
sizeof ( global - > name . savefile ) ) ;
2015-05-07 05:36:29 +00:00
2015-07-27 15:18:10 +00:00
if ( path_is_directory ( global - > dir . savestate ) )
strlcpy ( global - > name . savestate , global - > dir . savestate ,
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 }
} ;
2015-07-27 15:18:10 +00:00
global - > inited . core . no_content = false ;
global - > inited . 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-06-26 17:19:36 +00:00
global - > overrides_active = false ;
2014-09-02 15:05:15 +00:00
2015-06-26 17:19:36 +00:00
if ( argc < 2 )
{
2015-07-27 15:18:10 +00:00
global - > inited . core . type = CORE_TYPE_DUMMY ;
2015-06-26 17:19:36 +00:00
return ;
}
2012-03-25 22:04:12 +00:00
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 ] ) ;
2014-04-12 11:22:24 +00:00
rarch_fail ( 1 , " parse_input() " ) ;
}
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 ] ) ;
2012-08-16 19:20:38 +00:00
rarch_fail ( 1 , " parse_input() " ) ;
}
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-03-21 03:43:18 +00:00
global - > force_fullscreen = true ;
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-03-21 03:43:18 +00:00
global - > verbosity = true ;
2015-07-27 15:18:10 +00:00
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 ] ) ;
2012-04-21 21:25:32 +00:00
rarch_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 ) ) ;
global - > record . enable = 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-03-20 19:20:33 +00:00
strlcpy ( settings - > libretro , optarg ,
sizeof ( settings - > libretro ) ) ;
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-03-21 03:43:18 +00:00
strlcpy ( global - > bsv . movie_start_path , optarg ,
sizeof ( global - > bsv . movie_start_path ) ) ;
global - > bsv . movie_start_playback = ( c = = ' P ' ) ;
global - > bsv . movie_start_recording = ( c = = ' R ' ) ;
2011-11-18 17:03:24 +00:00
break ;
2011-11-20 19:19:05 +00:00
case ' M ' :
2015-06-14 17:56:01 +00:00
if ( ! strcmp ( 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
}
2015-06-14 17:56:01 +00:00
else if ( ! strcmp ( optarg , " noload-save " ) )
2015-07-27 15:18:10 +00:00
global - > sram . load_disable = true ;
2015-06-14 17:56:01 +00:00
else if ( ! strcmp ( optarg , " load-nosave " ) )
2015-07-27 15:18:10 +00:00
global - > sram . save_disable = true ;
2011-11-20 19:19:05 +00:00
else if ( strcmp ( optarg , " load-save " ) ! = 0 )
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 ] ) ;
2012-04-21 21:25:32 +00:00
rarch_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-06-30 20:39:13 +00:00
2015-06-30 20:36:17 +00:00
case RA_OPT_MENU :
2015-07-27 15:18:10 +00:00
global - > inited . 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
rarch_fail ( 1 , " network_cmd_send() " ) ;
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 ] ) ;
rarch_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-08-05 12:45:56 +00:00
rarch_main_set_max_frames ( strtoul ( optarg , NULL , 10 ) ) ;
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 :
global - > bsv . eof_exit = true ;
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 :
global - > log_file = fopen ( optarg , " wb " ) ;
break ;
# endif
2015-06-30 20:39:13 +00:00
case ' ? ' :
print_help ( argv [ 0 ] ) ;
rarch_fail ( 1 , " parse_input() " ) ;
2010-10-01 19:39:15 +00:00
default :
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " Error parsing arguments. \n " ) ;
rarch_fail ( 1 , " parse_input() " ) ;
2010-10-01 19:39:15 +00:00
}
2010-05-29 13:21:30 +00:00
}
2015-07-27 15:18:10 +00:00
if ( global - > inited . core . type = = CORE_TYPE_DUMMY )
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 " ) ;
2013-04-14 14:24:19 +00:00
rarch_fail ( 1 , " parse_input() " ) ;
}
}
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
2015-07-27 15:18:10 +00:00
global - > inited . core . no_content = true ;
2013-04-16 10:22:27 +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. */
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 ( ) ;
rarch_system_info_t * system = rarch_system_info_get_ptr ( ) ;
2015-03-21 03:43:18 +00:00
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_SAVEFILES_DEINIT ) ;
2014-10-03 10:26:29 +00:00
2015-03-21 03:43:18 +00:00
global - > savefiles = string_list_new ( ) ;
rarch_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-04-13 09:15:40 +00:00
void rarch_fill_pathnames ( void )
2014-10-05 09:01:50 +00:00
{
2015-03-21 03:43:18 +00:00
global_t * global = global_get_ptr ( ) ;
2014-10-05 09:01:50 +00:00
rarch_init_savefile_paths ( ) ;
2015-07-27 15:18:10 +00:00
strlcpy ( global - > bsv . movie_path , global - > name . savefile ,
2015-03-21 03:43:18 +00:00
sizeof ( global - > bsv . movie_path ) ) ;
2011-03-23 22:31:33 +00:00
2015-07-27 15:18:10 +00:00
if ( ! * global - > name . base )
2015-01-14 21:19:15 +00:00
return ;
2015-07-27 15:18:10 +00:00
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 ) ) ;
2011-01-12 20:57:55 +00:00
}
2015-03-22 06:28:45 +00:00
static bool init_state ( void )
2011-08-26 15:32:04 +00:00
{
2015-03-22 06:28:45 +00:00
driver_t * driver = driver_get_ptr ( ) ;
if ( ! driver )
return false ;
2015-03-18 18:40:00 +00:00
driver - > video_active = true ;
driver - > audio_active = true ;
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
2015-03-21 19:10:14 +00:00
static void main_clear_state_drivers ( void )
2014-09-30 19:50:05 +00:00
{
2015-03-21 19:10:14 +00:00
global_t * global = global_get_ptr ( ) ;
2015-03-21 23:29:30 +00:00
bool inited = false ;
if ( ! global )
return ;
2015-07-27 15:18:10 +00:00
inited = global - > inited . main ;
2015-03-21 18:31:38 +00:00
if ( ! inited )
return ;
2015-03-18 04:35:05 +00:00
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_DRIVERS_DEINIT ) ;
event_command ( EVENT_CMD_DRIVERS_INIT ) ;
2015-03-21 18:31:38 +00:00
}
static void main_init_state_config ( void )
{
unsigned i ;
settings_t * settings = config_get_ptr ( ) ;
if ( ! settings )
return ;
for ( i = 0 ; i < MAX_USERS ; i + + )
settings - > input . libretro_device [ i ] = RETRO_DEVICE_JOYPAD ;
2015-03-15 03:17:05 +00:00
}
2015-03-22 02:32:28 +00:00
void rarch_main_alloc ( void )
2015-03-21 18:31:38 +00:00
{
2015-03-21 00:32:57 +00:00
settings_t * settings = config_get_ptr ( ) ;
2014-09-30 19:50:05 +00:00
2015-03-21 00:47:06 +00:00
if ( settings )
config_free ( ) ;
settings = config_init ( ) ;
if ( ! settings )
return ;
2014-09-30 19:50:05 +00:00
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_HISTORY_DEINIT ) ;
2014-08-01 21:59:05 +00:00
2015-03-21 18:31:38 +00:00
rarch_main_clear_state ( ) ;
rarch_main_data_clear_state ( ) ;
2014-09-30 18:46:15 +00:00
}
2015-03-21 18:43:46 +00:00
/**
2015-03-22 02:32:28 +00:00
* rarch_main_new :
2015-03-21 18:43:46 +00:00
*
* Will teardown drivers and clears all
2015-06-30 13:26:14 +00:00
* internal state of the program .
2015-03-21 18:43:46 +00:00
* If @ inited is true , will initialize all
* drivers again after teardown .
* */
2015-03-22 02:32:28 +00:00
void rarch_main_new ( void )
2014-09-30 18:46:15 +00:00
{
2015-03-21 19:10:14 +00:00
main_clear_state_drivers ( ) ;
2015-03-21 18:43:46 +00:00
init_state ( ) ;
main_init_state_config ( ) ;
2015-03-21 03:43:18 +00:00
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_MSG_QUEUE_INIT ) ;
2012-01-14 15:08:54 +00:00
}
2011-08-26 15:32:04 +00:00
2015-03-22 02:32:28 +00:00
void rarch_main_free ( void )
2014-09-30 18:46:15 +00:00
{
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_MSG_QUEUE_DEINIT ) ;
event_command ( EVENT_CMD_DRIVERS_DEINIT ) ;
2015-06-12 15:31:56 +00:00
event_command ( EVENT_CMD_LOG_FILE_DEINIT ) ;
2015-03-15 05:50:08 +00:00
2015-03-22 02:41:20 +00:00
rarch_main_state_free ( ) ;
rarch_main_global_free ( ) ;
2015-03-21 18:43:46 +00:00
config_free ( ) ;
2014-09-30 18:46:15 +00:00
}
2015-01-14 02:04:44 +00:00
/*
2015-04-13 09:15:40 +00:00
* rarch_verify_api_version :
2015-01-14 02:04:44 +00:00
*
* Compare libretro core API version against API version
2015-06-30 13:26:14 +00:00
* used by the program .
2015-01-14 02:04:44 +00:00
*
* TODO - when libretro v2 gets added , allow for switching
* between libretro version backend dynamically .
* */
2015-04-13 09:15:40 +00:00
void rarch_verify_api_version ( void )
2012-04-07 09:55:37 +00:00
{
2012-04-21 21:25:32 +00:00
RARCH_LOG ( " Version of libretro API: %u \n " , pretro_api_version ( ) ) ;
2015-06-25 08:51:05 +00:00
RARCH_LOG ( " Compiled against API: %u \n " , RETRO_API_VERSION ) ;
2015-01-11 01:21:18 +00:00
2012-04-07 09:55:37 +00:00
if ( pretro_api_version ( ) ! = RETRO_API_VERSION )
2015-07-02 16:39:57 +00:00
RARCH_WARN ( " %s \n " , msg_hash_to_str ( MSG_LIBRETRO_ABI_BREAK ) ) ;
2012-04-07 09:55:37 +00:00
}
2015-01-11 01:21:18 +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 " ) ; \
rarch_fail ( 1 , " validate_cpu_features() " ) ; \
} while ( 0 )
2015-01-14 02:04:44 +00:00
/* validate_cpu_features:
*
* Validates CPU features for given processor architecture .
*
* Make sure we haven ' t compiled for something we cannot run .
2014-09-19 05:53:03 +00:00
* Ideally , code would get swapped out depending on CPU support ,
* but this will do for now .
2014-08-20 15:18:43 +00:00
*/
2012-11-01 21:31:24 +00:00
static void validate_cpu_features ( void )
{
2013-12-18 18:10:57 +00:00
uint64_t cpu = rarch_get_cpu_features ( ) ;
2013-12-19 02:45:17 +00:00
( void ) cpu ;
2012-11-01 21:31:24 +00:00
2012-11-02 20:25:54 +00:00
# ifdef __SSE__
2013-12-17 18:10:21 +00:00
if ( ! ( cpu & RETRO_SIMD_SSE ) )
2012-11-02 20:25:54 +00:00
FAIL_CPU ( " SSE " ) ;
# endif
2012-11-01 21:31:24 +00:00
# ifdef __SSE2__
2013-12-17 18:10:21 +00:00
if ( ! ( cpu & RETRO_SIMD_SSE2 ) )
2012-11-02 20:25:54 +00:00
FAIL_CPU ( " SSE2 " ) ;
2012-11-01 21:31:24 +00:00
# endif
# ifdef __AVX__
2013-12-17 18:10:21 +00:00
if ( ! ( cpu & RETRO_SIMD_AVX ) )
2012-11-02 20:25:54 +00:00
FAIL_CPU ( " AVX " ) ;
2012-11-01 21:31:24 +00:00
# endif
}
2015-01-14 02:04:44 +00:00
/**
2015-04-13 09:15:40 +00:00
* rarch_init_system_av_info :
2015-01-14 02:04:44 +00:00
*
* Initialize system A / V information by calling the libretro core ' s
* get_system_av_info function .
* */
2015-04-13 09:15:40 +00:00
void rarch_init_system_av_info ( void )
2014-10-05 17:13:03 +00:00
{
2015-05-20 16:57:17 +00:00
struct retro_system_av_info * av_info =
video_viewport_get_system_av_info ( ) ;
2015-03-18 05:47:22 +00:00
2015-05-20 16:57:17 +00:00
pretro_get_system_av_info ( av_info ) ;
2015-08-05 12:36:35 +00:00
rarch_main_set_frame_limit_last_time ( rarch_get_time_usec ( ) ) ;
2014-10-05 17:13:03 +00:00
}
2015-01-11 01:21:18 +00:00
/**
* rarch_main_init :
* @ argc : Count of ( commandline ) arguments .
* @ argv : ( Commandline ) arguments .
*
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-06-23 05:55:02 +00:00
global_t * global = global_get_ptr ( ) ;
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-03-21 03:43:18 +00:00
if ( ( sjlj_ret = setjmp ( global - > error_sjlj_context ) ) > 0 )
2012-01-14 15:08:54 +00:00
{
2015-03-21 03:43:18 +00:00
RARCH_ERR ( " Fatal error received in: \" %s \" \n " , global - > error_string ) ;
2012-01-14 15:08:54 +00:00
return sjlj_ret ;
}
2015-07-27 15:18:10 +00:00
global - > inited . error = true ;
global - > log_file = stderr ;
2012-05-03 22:14:42 +00:00
parse_input ( argc , argv ) ;
2015-03-21 03:43:18 +00:00
if ( global - > 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
}
2012-11-01 21:31:24 +00:00
validate_cpu_features ( ) ;
2012-01-28 14:47:02 +00:00
config_load ( ) ;
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
{
2015-07-27 15:18:10 +00:00
switch ( rarch_path_is_media_type ( global - > path . 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
2015-07-27 15:18:10 +00:00
global - > has_set . libretro = false ;
global - > inited . 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 )
{
2015-07-27 15:18:10 +00:00
global - > has_set . libretro = false ;
global - > inited . 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 ;
}
}
}
2015-07-27 15:18:10 +00:00
init_libretro_sym ( global - > inited . core . type ) ;
2015-06-25 12:30:32 +00:00
rarch_system_info_init ( ) ;
2012-04-07 09:55:37 +00:00
init_drivers_pre ( ) ;
2010-12-30 13:11:56 +00:00
2015-04-13 09:26:02 +00:00
if ( ! event_command ( EVENT_CMD_CORE_INIT ) )
2014-10-05 17:13:03 +00:00
goto error ;
2010-10-01 19:39:15 +00:00
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_DRIVERS_INIT ) ;
event_command ( EVENT_CMD_COMMAND_INIT ) ;
event_command ( EVENT_CMD_REWIND_INIT ) ;
event_command ( EVENT_CMD_CONTROLLERS_INIT ) ;
event_command ( EVENT_CMD_RECORD_INIT ) ;
event_command ( EVENT_CMD_CHEATS_INIT ) ;
event_command ( EVENT_CMD_REMAPPING_INIT ) ;
2011-01-23 01:23:20 +00:00
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_SAVEFILES_INIT ) ;
2015-02-16 10:33:15 +00:00
# if defined(GEKKO) && defined(HW_RVL)
2015-03-18 18:40:00 +00:00
{
2015-03-21 00:04:58 +00:00
settings_t * settings = config_get_ptr ( ) ;
2015-05-08 00:59:06 +00:00
2015-03-22 17:38:11 +00:00
if ( settings )
{
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_VIDEO_SET_ASPECT_RATIO ) ;
2015-03-22 17:38:11 +00:00
video_driver_set_aspect_ratio ( settings - > video . aspect_ratio_idx ) ;
}
2015-07-06 21:07:33 +00:00
unsigned width = 0 , height = 0 ;
( void ) width ;
( void ) height ;
width = global - > console . screen . resolutions . width ;
height = global - > console . screen . resolutions . height ;
video_driver_set_video_mode ( width , height , true ) ;
char msg [ PATH_MAX_LENGTH ] = { 0 } ;
snprintf ( msg , sizeof ( msg ) , " Resolution: %dx%d " , width , height ) ;
rarch_main_msg_queue_push ( msg , 1 , 100 , true ) ;
2015-03-18 18:40:00 +00:00
}
2015-02-16 10:33:15 +00:00
# endif
2014-10-13 05:35:18 +00:00
2015-07-27 15:18:10 +00:00
global - > inited . error = false ;
global - > inited . main = true ;
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 :
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_CORE_DEINIT ) ;
2010-05-26 19:27:37 +00:00
2015-07-27 15:18:10 +00:00
global - > inited . main = false ;
2012-01-14 13:08:43 +00:00
return 1 ;
}
2015-01-11 01:21:18 +00:00
/**
* rarch_main_init_wrap :
* @ args : Input arguments .
* @ argc : Count of arguments .
* @ argv : Arguments .
*
* Generates an @ argc and @ argv pair based on @ args
* of type rarch_main_wrap .
* */
2015-01-09 17:44:57 +00:00
void rarch_main_init_wrap ( const struct rarch_main_wrap * args ,
int * argc , char * * argv )
{
2015-06-12 15:31:28 +00:00
# ifdef HAVE_FILE_LOGGER
int i ;
# endif
2015-01-09 17:44:57 +00:00
* argc = 0 ;
argv [ ( * argc ) + + ] = strdup ( " retroarch " ) ;
if ( ! args - > no_content )
{
if ( args - > content_path )
{
RARCH_LOG ( " Using content: %s. \n " , args - > content_path ) ;
argv [ ( * argc ) + + ] = strdup ( args - > content_path ) ;
}
else
{
RARCH_LOG ( " No content, starting dummy core. \n " ) ;
argv [ ( * argc ) + + ] = strdup ( " --menu " ) ;
}
}
if ( args - > sram_path )
{
argv [ ( * argc ) + + ] = strdup ( " -s " ) ;
argv [ ( * argc ) + + ] = strdup ( args - > sram_path ) ;
}
if ( args - > state_path )
{
argv [ ( * argc ) + + ] = strdup ( " -S " ) ;
argv [ ( * argc ) + + ] = strdup ( args - > state_path ) ;
}
if ( args - > config_path )
{
argv [ ( * argc ) + + ] = strdup ( " -c " ) ;
argv [ ( * argc ) + + ] = strdup ( args - > config_path ) ;
}
# ifdef HAVE_DYNAMIC
if ( args - > libretro_path )
{
argv [ ( * argc ) + + ] = strdup ( " -L " ) ;
argv [ ( * argc ) + + ] = strdup ( args - > libretro_path ) ;
}
# endif
if ( args - > verbose )
argv [ ( * argc ) + + ] = strdup ( " -v " ) ;
# ifdef HAVE_FILE_LOGGER
for ( i = 0 ; i < * argc ; i + + )
RARCH_LOG ( " arg #%d: %s \n " , i , argv [ i ] ) ;
# endif
}
2014-09-03 16:16:49 +00:00
void rarch_main_set_state ( unsigned cmd )
{
2015-03-20 19:20:33 +00:00
driver_t * driver = driver_get_ptr ( ) ;
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 ( ) ;
2015-06-25 11:17:42 +00:00
rarch_system_info_t * system = rarch_system_info_get_ptr ( ) ;
2015-03-18 05:47:22 +00:00
2014-09-03 16:16:49 +00:00
switch ( cmd )
{
2014-09-29 11:27:28 +00:00
case RARCH_ACTION_STATE_MENU_RUNNING :
2014-10-03 17:19:52 +00:00
# ifdef HAVE_MENU
2015-06-30 23:07:22 +00:00
menu_driver_toggle ( true ) ;
2015-01-26 22:45:16 +00:00
2015-06-30 23:07:22 +00:00
/* Menu should always run with vsync on. */
event_command ( EVENT_CMD_VIDEO_SET_BLOCKING_STATE ) ;
/* Stop all rumbling before entering the menu. */
event_command ( EVENT_CMD_RUMBLE_STOP ) ;
2014-09-21 04:33:49 +00:00
2015-06-30 23:07:22 +00:00
if ( settings - > menu . pause_libretro )
event_command ( EVENT_CMD_AUDIO_STOP ) ;
2014-09-21 04:33:49 +00:00
2015-06-30 23:07:22 +00:00
/* Override keyboard callback to redirect to menu instead.
* We ' ll use this later for something . . .
* FIXME : This should probably be moved to menu_common somehow . */
if ( global )
{
global - > frontend_key_event = system - > key_event ;
system - > key_event = menu_input_key_event ;
system - > frame_time_last = 0 ;
2015-02-13 22:30:10 +00:00
}
2015-06-30 23:07:22 +00:00
menu_entries_set_refresh ( ) ;
menu_driver_set_alive ( ) ;
2015-07-16 09:57:50 +00:00
# endif
# ifdef HAVE_OVERLAY
if ( settings - > input . overlay_hide_in_menu )
event_command ( EVENT_CMD_OVERLAY_DEINIT ) ;
2014-10-03 17:19:52 +00:00
# endif
2014-09-03 16:36:46 +00:00
break ;
2014-09-03 16:16:49 +00:00
case RARCH_ACTION_STATE_LOAD_CONTENT :
2014-09-21 04:50:10 +00:00
# ifdef HAVE_MENU
2014-10-03 17:19:52 +00:00
/* If content loading fails, we go back to menu. */
2015-06-23 04:44:29 +00:00
if ( ! menu_load_content ( CORE_TYPE_PLAIN ) )
rarch_main_set_state ( RARCH_ACTION_STATE_MENU_RUNNING ) ;
# endif
if ( driver - > frontend_ctx & & driver - > frontend_ctx - > content_loaded )
driver - > frontend_ctx - > content_loaded ( ) ;
break ;
2015-06-23 06:16:14 +00:00
# ifdef HAVE_FFMPEG
2015-06-23 04:44:29 +00:00
case RARCH_ACTION_STATE_LOAD_CONTENT_FFMPEG :
# ifdef HAVE_MENU
/* If content loading fails, we go back to menu. */
if ( ! menu_load_content ( CORE_TYPE_FFMPEG ) )
2014-10-03 17:19:52 +00:00
rarch_main_set_state ( RARCH_ACTION_STATE_MENU_RUNNING ) ;
2014-09-21 04:50:10 +00:00
# endif
2015-03-18 18:40:00 +00:00
if ( driver - > frontend_ctx & & driver - > frontend_ctx - > content_loaded )
driver - > frontend_ctx - > content_loaded ( ) ;
2014-09-03 16:36:46 +00:00
break ;
2015-06-23 06:16:14 +00:00
# endif
2015-06-28 15:21:32 +00:00
case RARCH_ACTION_STATE_LOAD_CONTENT_IMAGEVIEWER :
# ifdef HAVE_MENU
/* If content loading fails, we go back to menu. */
if ( ! menu_load_content ( CORE_TYPE_IMAGEVIEWER ) )
rarch_main_set_state ( RARCH_ACTION_STATE_MENU_RUNNING ) ;
# endif
if ( driver - > frontend_ctx & & driver - > frontend_ctx - > content_loaded )
driver - > frontend_ctx - > content_loaded ( ) ;
break ;
2014-09-03 16:36:46 +00:00
case RARCH_ACTION_STATE_MENU_RUNNING_FINISHED :
2014-10-03 17:19:52 +00:00
# ifdef HAVE_MENU
2015-03-22 05:02:02 +00:00
menu_driver_toggle ( false ) ;
2015-05-19 18:11:57 +00:00
menu_driver_unset_alive ( ) ;
2014-09-29 10:44:17 +00:00
2015-03-18 18:40:00 +00:00
driver_set_nonblock_state ( driver - > nonblock_state ) ;
2014-09-29 10:44:17 +00:00
2015-03-21 22:43:00 +00:00
if ( settings & & settings - > menu . pause_libretro )
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_AUDIO_START ) ;
2014-09-29 10:44:17 +00:00
2014-09-29 12:55:35 +00:00
/* Prevent stray input from going to libretro core */
2015-03-18 18:40:00 +00:00
driver - > flushing_input = true ;
2014-09-29 12:55:35 +00:00
2014-09-29 10:44:17 +00:00
/* Restore libretro keyboard callback. */
2015-03-29 17:03:46 +00:00
if ( global )
2015-06-25 11:17:42 +00:00
system - > key_event = global - > frontend_key_event ;
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 )
2015-07-16 09:57:50 +00:00
event_command ( EVENT_CMD_OVERLAY_INIT ) ;
# endif
2014-09-03 16:36:46 +00:00
break ;
2014-09-03 16:16:49 +00:00
case RARCH_ACTION_STATE_QUIT :
2015-03-29 17:00:57 +00:00
if ( global )
2015-06-25 11:17:42 +00:00
system - > shutdown = true ;
2014-09-03 16:46:17 +00:00
rarch_main_set_state ( RARCH_ACTION_STATE_MENU_RUNNING_FINISHED ) ;
2014-09-03 16:16:49 +00:00
break ;
2014-09-12 03:14:43 +00:00
case RARCH_ACTION_STATE_FORCE_QUIT :
rarch_main_set_state ( RARCH_ACTION_STATE_QUIT ) ;
break ;
2014-09-03 16:16:49 +00:00
case RARCH_ACTION_STATE_NONE :
default :
break ;
}
}
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 ( ) ;
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_NETPLAY_DEINIT ) ;
event_command ( EVENT_CMD_COMMAND_DEINIT ) ;
2011-02-13 16:45:14 +00:00
2015-07-27 15:18:10 +00:00
if ( global - > sram . use )
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_AUTOSAVE_DEINIT ) ;
2015-03-15 05:50:08 +00:00
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_RECORD_DEINIT ) ;
event_command ( EVENT_CMD_SAVEFILES ) ;
2011-02-25 10:47:27 +00:00
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_REWIND_DEINIT ) ;
event_command ( EVENT_CMD_CHEATS_DEINIT ) ;
event_command ( EVENT_CMD_BSV_MOVIE_DEINIT ) ;
2015-03-15 05:50:08 +00:00
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_AUTOSAVE_STATE ) ;
2012-06-02 19:33:37 +00:00
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_CORE_DEINIT ) ;
2013-01-05 22:44:49 +00:00
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_TEMPORARY_CONTENT_DEINIT ) ;
event_command ( EVENT_CMD_SUBSYSTEM_FULLPATHS_DEINIT ) ;
event_command ( EVENT_CMD_SAVEFILES_DEINIT ) ;
2013-01-21 22:51:56 +00:00
2015-07-27 15:18:10 +00:00
global - > inited . main = false ;
2012-01-14 13:08:43 +00:00
}
2015-01-09 17:48:03 +00:00
2015-01-11 01:21:18 +00:00
/**
* rarch_playlist_load_content :
* @ playlist : Playlist handle .
* @ idx : Index in playlist .
*
* Initializes core and loads content based on playlist entry .
* */
2015-06-02 15:17:46 +00:00
void rarch_playlist_load_content ( void * data , unsigned idx )
2015-01-09 17:48:03 +00:00
{
2015-06-12 15:00:37 +00:00
const char * path = NULL ;
const char * core_path = NULL ;
2015-06-02 15:17:46 +00:00
content_playlist_t * playlist = ( content_playlist_t * ) data ;
2015-06-12 15:00:37 +00:00
menu_handle_t * menu = menu_driver_get_ptr ( ) ;
settings_t * settings = config_get_ptr ( ) ;
2015-01-09 17:48:03 +00:00
2015-06-02 15:17:46 +00:00
if ( ! playlist )
return ;
2015-01-09 17:48:03 +00:00
content_playlist_get_index ( playlist ,
2015-06-08 21:38:03 +00:00
idx , & path , NULL , & core_path , NULL , NULL , NULL ) ;
2015-01-09 17:48:03 +00:00
2015-03-20 19:20:33 +00:00
strlcpy ( settings - > libretro , core_path , sizeof ( settings - > libretro ) ) ;
2015-01-09 17:48:03 +00:00
2015-02-13 22:30:10 +00:00
if ( menu )
menu - > load_no_content = ( path ) ? false : true ;
2015-01-09 17:48:03 +00:00
rarch_environment_cb ( RETRO_ENVIRONMENT_EXEC , ( void * ) path ) ;
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_LOAD_CORE ) ;
2015-01-09 17:48:03 +00:00
}
2015-01-11 01:21:18 +00:00
/**
* rarch_defer_core :
* @ core_info : Core info list handle .
* @ dir : Directory . Gets joined with @ path .
* @ path : Path . Gets joined with @ dir .
* @ menu_label : Label identifier of menu setting .
2015-06-02 16:28:51 +00:00
* @ s : Deferred core path . Will be filled in
2015-01-11 01:21:18 +00:00
* by function .
2015-06-02 16:28:51 +00:00
* @ len : Size of @ s .
2015-01-11 01:21:18 +00:00
*
* Gets deferred core .
*
* Returns : 0 if there are multiple deferred cores and a
* selection needs to be made from a list , otherwise
2015-06-02 16:28:51 +00:00
* returns - 1 and fills in @ s with path to core .
2015-01-11 01:21:18 +00:00
* */
2015-01-09 17:48:03 +00:00
int rarch_defer_core ( core_info_list_t * core_info , const char * dir ,
const char * path , const char * menu_label ,
2015-06-02 16:28:51 +00:00
char * s , size_t len )
2015-01-09 17:48:03 +00:00
{
2015-06-12 15:00:37 +00:00
char new_core_path [ PATH_MAX_LENGTH ] = { 0 } ;
const core_info_t * info = NULL ;
size_t supported = 0 ;
settings_t * settings = config_get_ptr ( ) ;
global_t * global = global_get_ptr ( ) ;
2015-07-01 17:30:34 +00:00
uint32_t menu_label_hash = msg_hash_calculate ( menu_label ) ;
2015-01-09 17:48:03 +00:00
2015-06-02 16:28:51 +00:00
fill_pathname_join ( s , dir , path , len ) ;
2015-01-09 17:48:03 +00:00
# ifdef HAVE_COMPRESSION
if ( path_is_compressed_file ( dir ) )
{
/* In case of a compressed archive, we have to join with a hash */
/* We are going to write at the position of dir: */
2015-06-02 16:28:51 +00:00
rarch_assert ( strlen ( dir ) < strlen ( s ) ) ;
s [ strlen ( dir ) ] = ' # ' ;
2015-01-09 17:48:03 +00:00
}
# endif
if ( core_info )
2015-06-02 16:28:51 +00:00
core_info_list_get_supported_cores ( core_info , s , & info ,
2015-01-09 17:48:03 +00:00
& supported ) ;
2015-06-14 14:45:20 +00:00
if ( menu_label_hash = = MENU_LABEL_LOAD_CONTENT )
2015-01-09 17:48:03 +00:00
{
2015-07-27 15:18:10 +00:00
info = ( const core_info_t * ) & global - > core_info . current ;
2015-02-10 02:05:58 +00:00
if ( info )
{
strlcpy ( new_core_path , info - > path , sizeof ( new_core_path ) ) ;
supported = 1 ;
}
2015-01-09 17:48:03 +00:00
}
else
strlcpy ( new_core_path , info - > path , sizeof ( new_core_path ) ) ;
2015-05-07 23:06:14 +00:00
/* There are multiple deferred cores and a
2015-01-11 01:21:18 +00:00
* selection needs to be made from a list , return 0. */
if ( supported ! = 1 )
return 0 ;
2015-07-27 15:18:10 +00:00
strlcpy ( global - > path . fullpath , s , sizeof ( global - > path . fullpath ) ) ;
2015-01-11 01:21:18 +00:00
if ( path_file_exists ( new_core_path ) )
2015-03-20 19:20:33 +00:00
strlcpy ( settings - > libretro , new_core_path ,
sizeof ( settings - > libretro ) ) ;
2015-01-11 01:21:18 +00:00
return - 1 ;
2015-01-09 17:48:03 +00:00
}
2015-01-10 22:23:01 +00:00
/**
* rarch_replace_config :
* @ path : Path to config file to replace
* current config file with .
*
* Replaces currently loaded configuration file with
* another one . Will load a dummy core to flush state
* properly .
*
* Quite intrusive and error prone .
2015-01-09 17:48:03 +00:00
* Likely to have lots of small bugs .
* Cleanly exit the main loop to ensure that all the tiny details
* get set properly .
*
2015-01-10 22:23:01 +00:00
* This should mitigate most of the smaller bugs .
*
* Returns : true ( 1 ) if successful , false ( 0 ) if @ path was the
* same as the current config file .
* */
2015-01-09 17:48:03 +00:00
bool rarch_replace_config ( const char * path )
{
2015-03-20 19:20:33 +00:00
settings_t * settings = config_get_ptr ( ) ;
2015-03-21 03:43:18 +00:00
global_t * global = global_get_ptr ( ) ;
2015-03-20 19:20:33 +00:00
2015-05-07 23:06:14 +00:00
/* If config file to be replaced is the same as the
2015-01-09 17:48:03 +00:00
* current config file , exit . */
2015-07-27 15:18:10 +00:00
if ( ! strcmp ( path , global - > path . config ) )
2015-01-09 17:48:03 +00:00
return false ;
2015-07-27 15:18:10 +00:00
if ( settings - > config_save_on_exit & & * global - > path . config )
config_save_file ( global - > path . config ) ;
2015-01-09 17:48:03 +00:00
2015-07-27 15:18:10 +00:00
strlcpy ( global - > path . config , path , sizeof ( global - > path . config ) ) ;
2015-03-21 03:43:18 +00:00
global - > block_config_read = false ;
2015-03-20 19:20:33 +00:00
* settings - > libretro = ' \0 ' ; /* Load core in new config. */
2015-01-09 17:48:03 +00:00
2015-04-13 09:26:02 +00:00
event_command ( EVENT_CMD_PREPARE_DUMMY ) ;
2015-01-09 17:48:03 +00:00
return true ;
}