diff --git a/Makefile b/Makefile index 7fc22768a8..c27edef6ed 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +HAVE_FILE_LOGGER=1 + include config.mk TARGET = retroarch diff --git a/Makefile.common b/Makefile.common index 88ba717c9f..7f6b5ff3db 100644 --- a/Makefile.common +++ b/Makefile.common @@ -37,6 +37,10 @@ ifeq ($(TDM_GCC),) LDCXXFLAGS += -static-libstdc++ endif +ifeq ($(HAVE_FILE_LOGGER), 1) + CFLAGS += -DHAVE_FILE_LOGGER -Ilogger/netlogger +endif + CFLAGS += -I./libretro-common/include # Switches diff --git a/command_event.c b/command_event.c index 12a754d019..97f725d5fe 100644 --- a/command_event.c +++ b/command_event.c @@ -1550,7 +1550,7 @@ bool event_command(enum event_command cmd) if (!global) break; - if (global->log_file) + if (global->log_file && global->log_file != stderr) fclose(global->log_file); global->log_file = NULL; break; diff --git a/retroarch.c b/retroarch.c index 16c6ac823f..a98f89524f 100644 --- a/retroarch.c +++ b/retroarch.c @@ -53,9 +53,29 @@ #endif #endif +/* Descriptive names for options without short variant. Please keep the name in + sync with the option name. Order does not matter. */ +enum { + RA_OPT_MENU, + 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, + RA_OPT_SIZE, + RA_OPT_FEATURES, + RA_OPT_VERSION, + RA_OPT_EOF_EXIT, + RA_OPT_LOG_FILE, +}; + #include "config.features.h" -#define _PSUPP(var, name, desc) printf("\t%s:\n\t\t%s: %s\n", name, desc, _##var##_supp ? "yes" : "no") +#define _PSUPP(var, name, desc) printf(" %s:\n\t\t%s: %s\n", name, desc, _##var##_supp ? "yes" : "no") static void print_features(void) { puts(""); @@ -110,16 +130,10 @@ static void print_features(void) } #undef _PSUPP -/** - * print_help: - * - * Prints help message explaining RetroArch's commandline switches. - **/ -static void print_help(void) +static void print_version(void) { char str[PATH_MAX_LENGTH] = {0}; - puts("==================================================================="); #ifdef HAVE_GIT_VERSION printf(RETRO_FRONTEND ": Frontend for libretro -- v" PACKAGE_VERSION " -- %s --\n", rarch_git_version); #else @@ -128,63 +142,86 @@ static void print_help(void) rarch_info_get_capabilities(RARCH_CAPABILITIES_COMPILER, str, sizeof(str)); fprintf(stdout, "%s", str); fprintf(stdout, "Built: %s\n", __DATE__); +} + +/** + * print_help: + * + * Prints help message explaining RetroArch's commandline switches. + **/ +static void print_help(const char *arg0) +{ puts("==================================================================="); - puts("Usage: retroarch [content file] [options...]"); - puts("\t-h/--help: Show this help message."); - puts("\t--menu: Do not require content or libretro core to be loaded, starts directly in menu."); - puts("\t\tIf no arguments are passed to " RETRO_FRONTEND ", it is equivalent to using --menu as only argument."); - puts("\t--features: Prints available features compiled into " RETRO_FRONTEND "."); - puts("\t-s/--save: Path for save file (*.srm)."); - puts("\t-f/--fullscreen: Start " RETRO_FRONTEND " in fullscreen regardless of config settings."); - puts("\t-S/--savestate: Path to use for save states. If not selected, *.state will be assumed."); - puts("\t-c/--config: Path for config file." RARCH_DEFAULT_CONF_PATH_STR); - puts("\t--appendconfig: Extra config files are loaded in, and take priority over config selected in -c (or default)."); - puts("\t\tMultiple configs are delimited by '|'."); + print_version(); + puts("==================================================================="); + + printf("Usage: %s [OPTIONS]... [FILE]\n", arg0); + + puts(" -h, --help Show this help message."); + puts(" -v, --verbose Verbose logging."); + puts(" --log-file=FILE Log " RETRO_FRONTEND " messages to FILE."); + puts(" --version Show " RETRO_FRONTEND " version."); + puts(" --features Prints available features compiled into " RETRO_FRONTEND "."); + puts(" --menu Do not require content or libretro core to be loaded,\n" + " starts directly in menu. If no arguments are passed to\n" + " " RETRO_FRONTEND ", it is equivalent to using --menu as only argument."); + puts(" -s, --save=PATH Path for save files (*.srm)."); + puts(" -S, --savestate=PATH Path for the save state files (*.state)."); + puts(" -f, --fullscreen Start " RETRO_FRONTEND " in fullscreen regardless of config settings."); + puts(" -c, --config=FILE Path for config file." RARCH_DEFAULT_CONF_PATH_STR); + 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 '|'."); #ifdef HAVE_DYNAMIC - puts("\t-L/--libretro: Path to libretro implementation. Overrides any config setting."); + puts(" -L, --libretro=FILE Path to libretro implementation. Overrides any config setting."); #endif - puts("\t--subsystem: Use a subsystem of the libretro core. Multiple content files are loaded as multiple arguments."); - puts("\t\tIf a content file is skipped, use a blank (\"\") command line argument"); - puts("\t\tContent must be loaded in an order which depends on the particular subsystem used."); - puts("\t\tSee verbose log output to learn how a particular subsystem wants content to be loaded."); + 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"); - printf("\t-N/--nodevice: Disconnects controller device connected to port (1 to %d).\n", MAX_USERS); - printf("\t-A/--dualanalog: Connect a DualAnalog controller to port (1 to %d).\n", MAX_USERS); - printf("\t-d/--device: Connect a generic device into port of the device (1 to %d).\n", MAX_USERS); - puts("\t\tFormat is port:ID, where ID is an unsigned number corresponding to the particular device.\n"); + 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."); - puts("\t-P/--bsvplay: Playback a BSV movie file."); - puts("\t-R/--bsvrecord: Start recording a BSV movie file from the beginning."); - puts("\t--eof-exit: Exit upon reaching the end of the BSV movie file."); - puts("\t-M/--sram-mode: Takes an argument telling how SRAM should be handled in the session."); - puts("\t\t{no,}load-{no,}save describes if SRAM should be loaded, and if SRAM should be saved."); - puts("\t\tDo note that noload-save implies that save files will be deleted and overwritten."); + 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*."); #ifdef HAVE_NETPLAY - puts("\t-H/--host: Host netplay as user 1."); - puts("\t-C/--connect: Connect to netplay as user 2."); - puts("\t--port: Port used to netplay. Default is 55435."); - puts("\t-F/--frames: Sync frames when using netplay."); - puts("\t--spectate: Netplay will become spectating mode."); - puts("\t\tHost can live stream the game content to users that connect."); - puts("\t\tHowever, the client will not be able to play. Multiple clients can connect to the host."); + 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."); #endif - puts("\t--nick: Picks a username (for use with netplay). Not mandatory."); + puts(" --nick=NICK Picks a username (for use with netplay). Not mandatory."); #if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY) - puts("\t--command: Sends a command over UDP to an already running " RETRO_FRONTEND " process."); - puts("\t\tAvailable commands are listed if command is invalid."); + puts(" --command Sends a command over UDP to an already running " RETRO_FRONTEND " process."); + puts(" Available commands are listed if command is invalid."); #endif - puts("\t-r/--record: Path to record video file.\n\t\tUsing .mkv extension is recommended."); - puts("\t--recordconfig: Path to settings used during recording."); - puts("\t--size: Overrides output video size when recording (format: WIDTHxHEIGHT)."); - puts("\t-v/--verbose: Verbose logging."); - puts("\t-U/--ups: Specifies path for UPS patch that will be applied to content."); - puts("\t--bps: Specifies path for BPS patch that will be applied to content."); - puts("\t--ips: Specifies path for IPS patch that will be applied to content."); - puts("\t--no-patch: Disables all forms of content patching."); - puts("\t-D/--detach: Detach " RETRO_FRONTEND " from the running console. Not relevant for all platforms."); - puts("\t--max-frames: Runs for the specified number of frames, then exits.\n"); + 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."); + puts(" -D, --detach Detach " RETRO_FRONTEND " from the running console. Not relevant for all platforms."); + puts(" --max-frames=NUMBER\n" + " Runs for the specified number of frames, then exits.\n"); } static void set_basename(const char *path) @@ -362,7 +399,11 @@ static void parse_input(int argc, char *argv[]) global_t *global = global_get_ptr(); global->libretro_no_content = false; +#ifdef HAVE_DYNAMIC + global->libretro_dummy = true; +#else global->libretro_dummy = false; +#endif global->has_set_save_path = false; global->has_set_state_path = false; global->has_set_libretro = false; @@ -389,12 +430,6 @@ static void parse_input(int argc, char *argv[]) global->overrides_active = false; - if (argc < 2) - { - global->libretro_dummy = true; - return; - } - /* Make sure we can call parse_input several times ... */ optind = 0; @@ -402,45 +437,49 @@ static void parse_input(int argc, char *argv[]) const struct option opts[] = { #ifdef HAVE_DYNAMIC - { "libretro", 1, NULL, 'L' }, + { "libretro", 1, NULL, 'L' }, #endif - { "menu", 0, &val, 'M' }, - { "help", 0, NULL, 'h' }, - { "save", 1, NULL, 's' }, - { "fullscreen", 0, NULL, 'f' }, - { "record", 1, NULL, 'r' }, + { "menu", 0, &val, RA_OPT_MENU }, + { "help", 0, NULL, 'h' }, + { "save", 1, NULL, 's' }, + { "fullscreen", 0, NULL, 'f' }, + { "record", 1, NULL, 'r' }, { "recordconfig", 1, &val, 'R' }, - { "size", 1, &val, 's' }, - { "verbose", 0, NULL, 'v' }, - { "config", 1, NULL, 'c' }, + { "size", 1, &val, RA_OPT_SIZE }, + { "verbose", 0, NULL, 'v' }, + { "config", 1, NULL, 'c' }, { "appendconfig", 1, &val, 'C' }, - { "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' }, + { "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' }, #ifdef HAVE_NETPLAY - { "host", 0, NULL, 'H' }, - { "connect", 1, NULL, 'C' }, - { "frames", 1, NULL, 'F' }, - { "port", 1, &val, 'p' }, - { "spectate", 0, &val, 'S' }, + { "host", 0, NULL, 'H' }, + { "connect", 1, NULL, 'C' }, + { "frames", 1, NULL, 'F' }, + { "port", 1, &val, RA_OPT_PORT }, + { "spectate", 0, &val, RA_OPT_SPECTATE }, #endif - { "nick", 1, &val, 'N' }, + { "nick", 1, &val, 'N' }, #if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY) - { "command", 1, &val, 'c' }, + { "command", 1, &val, RA_OPT_COMMAND }, +#endif + { "ups", 1, NULL, 'U' }, + { "bps", 1, &val, RA_OPT_BPS }, + { "ips", 1, &val, RA_OPT_IPS }, + { "no-patch", 0, &val, RA_OPT_NO_PATCH }, + { "detach", 0, NULL, 'D' }, + { "features", 0, &val, RA_OPT_FEATURES }, + { "subsystem", 1, NULL, 'Z' }, + { "max-frames", 1, NULL, 'm' }, + { "eof-exit", 0, &val, RA_OPT_EOF_EXIT }, + { "version", 0, &val, RA_OPT_VERSION }, +#ifdef HAVE_FILE_LOGGER + { "log-file", 1, &val, RA_OPT_LOG_FILE }, #endif - { "ups", 1, NULL, 'U' }, - { "bps", 1, &val, 'B' }, - { "ips", 1, &val, 'I' }, - { "no-patch", 0, &val, 'n' }, - { "detach", 0, NULL, 'D' }, - { "features", 0, &val, 'f' }, - { "subsystem", 1, NULL, 'Z' }, - { "max-frames", 1, NULL, 'm' }, - { "eof-exit", 0, &val, 'e' }, { NULL, 0, NULL, 0 } }; @@ -476,7 +515,7 @@ static void parse_input(int argc, char *argv[]) switch (c) { case 'h': - print_help(); + print_help(argv[0]); exit(0); case 'Z': @@ -500,7 +539,7 @@ static void parse_input(int argc, char *argv[]) if (port < 1 || port > MAX_USERS) { RARCH_ERR("Connect device to a valid port.\n"); - print_help(); + print_help(argv[0]); rarch_fail(1, "parse_input()"); } settings->input.libretro_device[port - 1] = id; @@ -513,7 +552,7 @@ static void parse_input(int argc, char *argv[]) if (port < 1 || port > MAX_USERS) { RARCH_ERR("Connect dualanalog to a valid port.\n"); - print_help(); + print_help(argv[0]); rarch_fail(1, "parse_input()"); } settings->input.libretro_device[port - 1] = RETRO_DEVICE_ANALOG; @@ -546,7 +585,7 @@ static void parse_input(int argc, char *argv[]) if (port < 1 || port > MAX_USERS) { RARCH_ERR("Disconnect device from a valid port.\n"); - print_help(); + print_help(argv[0]); rarch_fail(1, "parse_input()"); } settings->input.libretro_device[port - 1] = RETRO_DEVICE_NONE; @@ -581,6 +620,7 @@ static void parse_input(int argc, char *argv[]) sizeof(settings->libretro)); global->has_set_libretro = true; } + global->libretro_dummy = false; break; #endif case 'P': @@ -604,7 +644,7 @@ static void parse_input(int argc, char *argv[]) else if (strcmp(optarg, "load-save") != 0) { RARCH_ERR("Invalid argument in --sram-mode.\n"); - print_help(); + print_help(argv[0]); rarch_fail(1, "parse_input()"); } break; @@ -646,33 +686,33 @@ static void parse_input(int argc, char *argv[]) runloop->frames.video.max = strtoul(optarg, NULL, 10); break; - case 0: + case 0: /* options without short variant */ switch (val) { - case 'M': + case RA_OPT_MENU: global->libretro_dummy = true; break; #ifdef HAVE_NETPLAY - case 'p': + case RA_OPT_PORT: global->has_set_netplay_ip_port = true; global->netplay_port = strtoul(optarg, NULL, 0); break; - case 'S': + case RA_OPT_SPECTATE: global->has_set_netplay_mode = true; global->netplay_is_spectate = true; break; #endif - case 'N': + case RA_OPT_NICK: global->has_set_username = true; strlcpy(settings->username, optarg, sizeof(settings->username)); break; #if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY) - case 'c': + case RA_OPT_COMMAND: if (network_cmd_send(optarg)) exit(0); else @@ -680,60 +720,69 @@ static void parse_input(int argc, char *argv[]) break; #endif - case 'C': + case RA_OPT_APPENDCONFIG: strlcpy(global->append_config_path, optarg, sizeof(global->append_config_path)); break; - case 'B': + case RA_OPT_BPS: strlcpy(global->bps_name, optarg, sizeof(global->bps_name)); global->bps_pref = true; global->has_set_bps_pref = true; break; - case 'I': + case RA_OPT_IPS: strlcpy(global->ips_name, optarg, sizeof(global->ips_name)); global->ips_pref = true; global->has_set_ips_pref = true; break; - case 'n': + case RA_OPT_NO_PATCH: global->block_patch = true; break; - case 's': + 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(); + print_help(argv[0]); rarch_fail(1, "parse_input()"); } break; } - case 'R': + case RA_OPT_RECORDCONFIG: strlcpy(global->record.config, optarg, sizeof(global->record.config)); break; - case 'f': + case RA_OPT_FEATURES: print_features(); exit(0); - case 'e': + case RA_OPT_EOF_EXIT: global->bsv.eof_exit = true; break; + case RA_OPT_VERSION: + print_version(); + exit(0); + +#ifdef HAVE_FILE_LOGGER + case RA_OPT_LOG_FILE: + global->log_file = fopen(optarg, "wb"); + break; +#endif default: break; } break; case '?': - print_help(); + print_help(argv[0]); rarch_fail(1, "parse_input()"); default: @@ -951,8 +1000,8 @@ void rarch_main_new(void) void rarch_main_free(void) { event_command(EVENT_CMD_MSG_QUEUE_DEINIT); - event_command(EVENT_CMD_LOG_FILE_DEINIT); event_command(EVENT_CMD_DRIVERS_DEINIT); + event_command(EVENT_CMD_LOG_FILE_DEINIT); rarch_main_state_free(); rarch_main_global_free(); @@ -1081,6 +1130,7 @@ int rarch_main_init(int argc, char *argv[]) return sjlj_ret; } global->error_in_init = true; + global->log_file = stderr; parse_input(argc, argv); if (global->verbosity) @@ -1153,6 +1203,10 @@ error: void rarch_main_init_wrap(const struct rarch_main_wrap *args, int *argc, char **argv) { +#ifdef HAVE_FILE_LOGGER + int i; +#endif + *argc = 0; argv[(*argc)++] = strdup("retroarch"); diff --git a/retroarch_logger.h b/retroarch_logger.h index aa5aa3a314..11d2a1c512 100644 --- a/retroarch_logger.h +++ b/retroarch_logger.h @@ -20,7 +20,11 @@ #include #include -#if defined(HAVE_FILE_LOGGER) && defined(RARCH_INTERNAL) +#if defined(HAVE_FILE_LOGGER) && defined(RARCH_INTERNAL) && !defined(IS_JOYCONFIG) +#ifdef __cplusplus +extern "C" +#endif +FILE *rarch_main_log_file(void); #define LOG_FILE (rarch_main_log_file()) #else #define LOG_FILE (stderr) diff --git a/tools/retroarch-joyconfig-griffin.c b/tools/retroarch-joyconfig-griffin.c index 89a13fd033..4a63722fb4 100644 --- a/tools/retroarch-joyconfig-griffin.c +++ b/tools/retroarch-joyconfig-griffin.c @@ -14,6 +14,8 @@ * If not, see . */ +#define IS_JOYCONFIG + #include "retroarch-joyconfig.c" #include "../libretro-common/dynamic/dylib.c"