Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 116 additions & 2 deletions src/desktop/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <glad/glad.h>
#endif
#if defined(ENABLE_LEGACY_GL) || defined(ENABLE_MODERN_GL)
Expand All @@ -48,6 +48,7 @@

#include "utils.h"
#include "profiler.h"
#include "localization.h"

enum GraphicsAPI gfx;

Expand Down Expand Up @@ -276,10 +277,120 @@ static char** extractRunnerArguments(char* rawArguments) {
return array;
}

static void printUsage(const char *argv0) {
fprintf(
stderr,
"Usage: %s <path to data.win or game.unx>\n"
" --help - %s\n"
" --screenshot <filename> - %s\n"
" --screenshot-at-frame <frame> - %s\n"
" --screenshot-surfaces <filename> - %s\n"
" --screenshot-surfaces-at-frame <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 <frame> - %s\n"
" --trace-bytecode-after-frame <frame> - %s\n"
//" --dump-frame <frame> - %s\n"
//" --dump-frame-json - %s\n"
//" --dump-frame-json-file - %s\n"
" --speed <speed> - %s\n"
" --fast-forward-speed <speed> - %s\n"
" --seed <seed> - %s\n"
" --debug - %s\n"
//" --disassemble - %s\n"
//" --record-inputs - %s\n"
//" --playback-inputs - %s\n"
" --renderer <renderer> - %s\n"
" --lazy-rooms - %s\n"
//" --eager-room - %s\n"
" --os-type <os> - %s\n"
" --window-size <dimentions> - %s\n"
" --widescreen-hack <aspect ratio> - %s\n"
" --profile-gml-scripts - %s\n"
" --save-folder <directory> - %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'},
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -596,7 +710,7 @@ static void parseCommandLineArgs(CommandLineArgs* args, int argc, char* argv[])
break;
}
default:
fprintf(stderr, "Usage: %s <path to data.win or game.unx>\n", argv[0]);
printUsage(argv[0]);
exit(1);
}
}
Expand Down
76 changes: 76 additions & 0 deletions src/localization.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include "localization.h"

#include <string.h>
#include <stdarg.h>

/*
* 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);
}
20 changes: 20 additions & 0 deletions src/localization.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include <stdio.h>

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, ...);
Loading