diff --git a/src/desktop/main.c b/src/desktop/main.c index da00922b..80811207 100644 --- a/src/desktop/main.c +++ b/src/desktop/main.c @@ -24,7 +24,7 @@ #include "runner.h" #include "input_recording.h" #include "debug_overlay.h" -#if defined(ENABLE_LEGACY_GL) || defined(ENABLE_MODERN_GL) || ((defined(USE_GLFW3) || defined(USE_GLFW2)) && defined(ENABLE_SW_RENDERER) ) +#if defined(ENABLE_LEGACY_GL) || defined(ENABLE_MODERN_GL) || ((defined(USE_GLFW3) || defined(USE_GLFW2)) && defined(ENABLE_SW_RENDERER)) #include #endif #if defined(ENABLE_LEGACY_GL) || defined(ENABLE_MODERN_GL) @@ -48,6 +48,7 @@ #include "utils.h" #include "profiler.h" +#include "localization.h" enum GraphicsAPI gfx; @@ -276,10 +277,120 @@ static char** extractRunnerArguments(char* rawArguments) { return array; } +static void printUsage(const char *argv0) { + fprintf( + stderr, + "Usage: %s \n" + " --help - %s\n" + " --screenshot - %s\n" + " --screenshot-at-frame - %s\n" + " --screenshot-surfaces - %s\n" + " --screenshot-surfaces-at-frame - %s\n" +#ifndef USE_GLFW2 + " --headless - %s\n" +#endif + " --print-rooms - %s\n" + //" --print-objects - %s\n" + " --print-declared-functions - %s\n" + " --print-unknown-functions - %s\n" + " --trace-variable-reads - %s\n" + " --trace-variable-writes - %s\n" + " --trace-function-calls - %s\n" + " --trace-alarms - %s\n" + " --trace-instance-lifecycles - %s\n" + " --trace-events - %s\n" + " --trace-collisions - %s\n" + " --trace-event-inherited - %s\n" + " --trace-tiles - %s\n" + " --trace-opcodes - %s\n" + " --trace-stack - %s\n" + " --trace-frames - %s\n" + " --always-log-unknown-functions - %s\n" + " --always-log-stubbed-functions - %s\n" + " --exit-at-frame - %s\n" + " --trace-bytecode-after-frame - %s\n" + //" --dump-frame - %s\n" + //" --dump-frame-json - %s\n" + //" --dump-frame-json-file - %s\n" + " --speed - %s\n" + " --fast-forward-speed - %s\n" + " --seed - %s\n" + " --debug - %s\n" + //" --disassemble - %s\n" + //" --record-inputs - %s\n" + //" --playback-inputs - %s\n" + " --renderer - %s\n" + " --lazy-rooms - %s\n" + //" --eager-room - %s\n" + " --os-type - %s\n" + " --window-size - %s\n" + " --widescreen-hack - %s\n" + " --profile-gml-scripts - %s\n" + " --save-folder - %s\n" + //" --game-args - %s\n" +#ifdef EABLE_VM_OPCODE_PROFILER + " --profile-opcodes - %s\n" +#endif + , + argv0, + getLocStr("Show this message", "help.help"), + getLocStr("Specify the filename for screenshots", "help.screenshot"), + getLocStr("Take a screenshot at the specified frame", "help.screenshot-at-frame"), + getLocStr("Take a screenshot of all surfaces at the specified frame", "help.screenshot-surfaces"), + getLocStr("Specify the filename for surface screenshots", "help.screenshot-surfaces-at-frame"), +#ifndef USE_GLFW2 + getLocStr("Launch without a window", "help.headless"), +#endif + getLocStr("Print all the rooms in the game and exit", "help.print-rooms"), + //getLocStr("", "help.print-objects"), + getLocStr("Print all declared functions in the game and exit", "help.print-declared-functions"), + getLocStr("Print all unknown functions used by the game and exit", "help.print-unknown-functions"), + getLocStr("Trace variable reads", "help.trace-variable-reads"), + getLocStr("Trace variable writes", "help.trace-variable-writes"), + getLocStr("Trace function calls", "help.trace-function-calls"), + getLocStr("Trace alarms", "help.trace-alarms"), + getLocStr("Trace instance creations and deletions", "help.trace-instance-lifecycles"), + getLocStr("Trace events", "help.trace-events"), + getLocStr("Trace collisions between instances", "help.trace-collisions"), + getLocStr("Trace event inherited calls", "help.trace-event-inherited"), + getLocStr("Trace drawn tiles", "help.trace-tiles"), + getLocStr("Trace opcodes", "help.trace-opcodes"), + getLocStr("Trace stack", "help.trace-stack"), + getLocStr("Log frametimes", "help.trace-frames"), + getLocStr("Always log unknown function calls instead of once per script", "help.always-log-unknown-functions"), + getLocStr("Always log stubbed function calls instead of once per script", "help.always-log-stubbed-functions"), + getLocStr("Exit at the specified frame", "help.exit-at-frame"), + getLocStr("Delay stack and opcode tracing until the specified frame", "help.trace-bytecode-after-frame"), + //getLocStr("", "help.dump-frame"), + //getLocStr("", "help.dump-frame-json"), + //getLocStr("", "help.dump-frame-json-file"), + getLocStr("Set a normal speed multiplier", "help.speed"), + getLocStr("Set a fast-forward speed multiplier", "help.fast-forward-speed"), + getLocStr("Seed for the random number generator", "help.seed"), + getLocStr("Enable debug mode", "help.debug"), + //getLocStr("", "help.disassemble"), + //getLocStr("", "help.record-inputs"), + //getLocStr("", "help.playback-inputs"), + getLocStr("Set the rendering API", "help.renderer"), + getLocStr("Lazily load rooms, increases load times but reduces memory usage", "help.lazy-rooms"), + //getLocStr("", "help.eager-room"), + getLocStr("Set the reported OS type", "help.os-type"), + getLocStr("Set a custom window size", "help.window-size"), + getLocStr("Set a custom aspect ratio", "help.widescreen-hack"), + getLocStr("Log which GML scripts are the heaviest in terms of time and executed instructions", "help.profile-gml-scripts"), + getLocStr("Set the directory will save files will be stored", "help.save-folder") + //getLocStr("", "help.game-args") +#ifdef EABLE_VM_OPCODE_PROFILER + , getLocStr("Rank which GML opcodes were executed the most", "help.profile-opcodes") +#endif + ); +} + static void parseCommandLineArgs(CommandLineArgs* args, int argc, char* argv[]) { memset(args, 0, sizeof(CommandLineArgs)); static struct option longOptions[] = { + {"help", no_argument, nullptr, 'H'}, {"screenshot", required_argument, nullptr, 's'}, {"screenshot-at-frame", required_argument, nullptr, 'f'}, {"screenshot-surfaces", required_argument, nullptr, 'U'}, @@ -351,6 +462,9 @@ static void parseCommandLineArgs(CommandLineArgs* args, int argc, char* argv[]) int opt; while ((opt = getopt_long(argc, argv, "", longOptions, nullptr)) != -1) { switch (opt) { + case 'H': + printUsage(argv[0]); + exit(0); case 's': args->screenshotPattern = optarg; break; @@ -596,7 +710,7 @@ static void parseCommandLineArgs(CommandLineArgs* args, int argc, char* argv[]) break; } default: - fprintf(stderr, "Usage: %s \n", argv[0]); + printUsage(argv[0]); exit(1); } } diff --git a/src/localization.c b/src/localization.c new file mode 100644 index 00000000..879f238d --- /dev/null +++ b/src/localization.c @@ -0,0 +1,76 @@ +#include "localization.h" + +#include +#include + +/* + * To add a language, create a category array and one or more string arrays. + * Then, add your language to the switch statement in getLocStr(). + * + * Below is a language called 'sillylang' that exists to act as an example + * of how you would add a language. It should be removed once at least one + * real language is added to this file. + * + * The only string sillylang translates is the description for the --help + * option in the --help usage message, it translates 'Show this message' + * to 'im silly :3'. + * + * If a string is unhandled by your translation, it will show up as the + * fallback string passed to getLocStr(). This will be an English version + * of the text. + */ + +/* +const struct localized_string help_strings_sillylang[] = { + { "help", "im silly :3" }, + { NULL, NULL } +}; + +const struct string_category string_categories_sillylang[] = { + { "help", help_strings_sillylang }, + { NULL, NULL } +}; +*/ + +static enum language getLanguage(void) { + /* + * TODO: add more languages + * Also prolly don't fetch it again every time cuz this + * function might get called frequently, so have a static + * variable that gets inited once and subsequent calls + * can return the cached value. + */ + return BS_LANG_ENGLISH; +} + +const char *getLocStr(const char *fallback, const char *id) { + if (!id) + return fallback; + const struct string_category *categories; + switch (getLanguage()) { + /* + case BS_LANG_SILLY: + categories = string_categories_sillylang; + break; + */ + default: + return fallback; + } + size_t id_dot = 0; + while (id[id_dot] != '.') + ++id_dot; + for (size_t category = 0; categories[category].name; ++category) + if (strncmp(categories[category].name, id, id_dot) == 0) + for (size_t i = 0; categories[category].strings[i].name; ++i) + if (strcmp(categories[category].strings[i].name, id + id_dot + 1) == 0) + return categories[category].strings[i].string; + + return fallback; +} + +void locLog(const char *fallback, const char *id, ...) { + va_list ap; + va_start(ap, id); + vfprintf(stderr, getLocStr(fallback, id), ap); + va_end(ap); +} diff --git a/src/localization.h b/src/localization.h new file mode 100644 index 00000000..3160bfc5 --- /dev/null +++ b/src/localization.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +enum language { + BS_LANG_ENGLISH +}; + +struct localized_string { + const char *name; + const char *string; +}; + +struct string_category { + const char *name; + const struct localized_string *strings; +}; + +const char *getLocStr(const char *fallback, const char *id); +void locLog(const char *fallback, const char *id, ...);