diff --git a/docs/COMMAND_LINE.md b/docs/COMMAND_LINE.md new file mode 100644 index 000000000..9fca2d295 --- /dev/null +++ b/docs/COMMAND_LINE.md @@ -0,0 +1,20 @@ +# Command line options + +Currently the following command line interface options are available: + +`-g/--gold` (legacy: `-gold`): + Runs the Unfinished Business or the Golden Mask expansion pack, depending + on the game. + +`--demo-pc` (TR1X only, legacy: `-demo_pc`): + Runs the PC demo level. + +`-l/--level `: + Runs the game immediately launching it into the specified level. + The path should be absolute. Internally, this option uses + `TR*X_gameflow_level.json5` as a template instructing it how to run the + game. + +`-s/--save `: + Runs the game immediately loading a specific save slot. The first save + starts at `num=1`. This option can be combined with `-l/--level`. diff --git a/docs/tr1/CHANGELOG.md b/docs/tr1/CHANGELOG.md index 6ca1234bd..7047d5433 100644 --- a/docs/tr1/CHANGELOG.md +++ b/docs/tr1/CHANGELOG.md @@ -6,6 +6,8 @@ - added support for aspect ratio-specific images (#1840) - added an option to wraparound when scrolling UI dialogs, such as save/load (#2834) - changed the `draw_distance_fade` and `draw_distance_max` to `fog_start` and `fog_end` +- added aliases to CLI options (`-gold` becomes `-g/--gold`, `-demo_pc` becomes `--demo-pc`) +- added a `--help` CLI option (may not output anything on Windows machines – OS bug) - changed `Select Detail` dialog title to `Graphic Options` - changed the number of static mesh slots from 50 to 256 (#2734) - changed the "enable EIDOS logo" option to disable the Core Design and Bink Video Codec FMVs as well; renamed to "enable legal" (#2741) diff --git a/docs/tr2/CHANGELOG.md b/docs/tr2/CHANGELOG.md index fa31d551c..11a28dcb9 100644 --- a/docs/tr2/CHANGELOG.md +++ b/docs/tr2/CHANGELOG.md @@ -1,4 +1,6 @@ ## [Unreleased](https://github.com/LostArtefacts/TRX/compare/tr2-1.0.1...develop) - ××××-××-×× +- added aliases to CLI options (`-gold` becomes `-g/--gold`) +- added a `--help` CLI option (may not output anything on Windows machines – OS bug) - changed the sound dialog appearance (repositioned, added text labels and arrows) - fixed Lara voiding if she stops on a tile with a closing door, and the door isn't on a portal (#2848) - fixed guns carried by enemies not being converted to ammo if Lara has picked up the same gun elsewhere in the same level (#2856) diff --git a/src/libtrx/game/shell/main.c b/src/libtrx/game/shell/main.c index 1a29106ab..4e3ce7d41 100644 --- a/src/libtrx/game/shell/main.c +++ b/src/libtrx/game/shell/main.c @@ -21,13 +21,11 @@ int main(int argc, char *argv[]) Log_Init(log_path); Memory_FreePointer(&log_path); - LOG_INFO("Game directory: %s", File_GetGameDirectory()); - m_ArgCount = argc; m_ArgStrings = (const char **)argv; Shell_Setup(); - Shell_Main(); - Shell_Terminate(0); - return 0; + int32_t exit_code = Shell_Main(); + Shell_Terminate(exit_code); + return exit_code; } diff --git a/src/libtrx/include/libtrx/game/shell.h b/src/libtrx/include/libtrx/game/shell.h index 3128bda38..e1cfc303a 100644 --- a/src/libtrx/include/libtrx/game/shell.h +++ b/src/libtrx/include/libtrx/game/shell.h @@ -12,7 +12,7 @@ extern void Shell_Shutdown(void); extern SDL_Window *Shell_GetWindow(void); void Shell_Setup(void); -extern void Shell_Main(void); +extern int32_t Shell_Main(void); void Shell_Terminate(int32_t exit_code); void Shell_ExitSystem(const char *message); void Shell_ExitSystemFmt(const char *fmt, ...); diff --git a/src/tr1/game/output.c b/src/tr1/game/output.c index 9bed2681b..c63c73c94 100644 --- a/src/tr1/game/output.c +++ b/src/tr1/game/output.c @@ -49,6 +49,7 @@ typedef struct { int32_t thickness; } LIGHTNING; +static bool m_Initialized = false; static int32_t m_LightningCount = 0; static LIGHTNING m_LightningTable[MAX_LIGHTNINGS]; static int32_t m_TextureMap[GFX_MAX_TEXTURES] = { GFX_NO_TEXTURE }; @@ -385,6 +386,11 @@ static void M_DrawSprite( bool Output_Init(void) { + if (m_Initialized) { + return true; + } + m_Initialized = true; + for (int32_t i = 0; i < GFX_MAX_TEXTURES; i++) { m_TextureMap[i] = GFX_NO_TEXTURE; m_TextureSurfaces[i] = nullptr; @@ -406,6 +412,11 @@ bool Output_Init(void) void Output_Shutdown(void) { + if (!m_Initialized) { + return; + } + m_Initialized = false; + Output_Meshes_Shutdown(); Output_Sprites_Shutdown(); Output_Textures_Shutdown(); diff --git a/src/tr1/game/shell.c b/src/tr1/game/shell.c index f892719ba..72910c037 100644 --- a/src/tr1/game/shell.c +++ b/src/tr1/game/shell.c @@ -81,11 +81,22 @@ static SHELL_ARGS m_Args = { static const char *m_CurrentGameFlowPath; -static void M_ParseArgs(SHELL_ARGS *out_args); +static void M_ShowHelp(void); +static bool M_ParseArgs(SHELL_ARGS *out_args); static void M_LoadConfig(void); static void M_HandleConfigChange(const EVENT *event, void *data); -static void M_ParseArgs(SHELL_ARGS *const out_args) +static void M_ShowHelp(void) +{ + puts("Currently available options:"); + puts(""); + puts("-g/--gold: launch The Unfinished Business expansion pack."); + puts(" --demo-pc: launch the PC demo level file."); + puts("-l/--level : launch a specific level file."); + puts("-s/--save : launch from a specific save slot (starts at 1)."); +} + +static bool M_ParseArgs(SHELL_ARGS *const out_args) { const char **args = nullptr; int32_t arg_count = 0; @@ -94,10 +105,15 @@ static void M_ParseArgs(SHELL_ARGS *const out_args) out_args->mod = M_MOD_OG; for (int32_t i = 0; i < arg_count; i++) { - if (!strcmp(args[i], "-gold")) { + if (!strcmp(args[i], "-h") || !strcmp(args[i], "--help")) { + M_ShowHelp(); + return false; + } + if (!strcmp(args[i], "-g") || !strcmp(args[i], "--gold") + || !strcmp(args[i], "-gold")) { out_args->mod = M_MOD_UB; } - if (!strcmp(args[i], "-demo_pc")) { + if (!strcmp(args[i], "--demo-pc") || !strcmp(args[i], "-demo_pc")) { out_args->mod = M_MOD_DEMO_PC; } if ((!strcmp(args[i], "-l") || !strcmp(args[i], "--level")) @@ -112,6 +128,7 @@ static void M_ParseArgs(SHELL_ARGS *const out_args) } } } + return true; } static void M_HandleConfigChange(const EVENT *const event, void *const data) @@ -174,9 +191,11 @@ const char *Shell_GetGameFlowPath(void) return m_ModPaths[m_Args.mod].game_flow_path; } -void Shell_Main(void) +int32_t Shell_Main(void) { - M_ParseArgs(&m_Args); + if (!M_ParseArgs(&m_Args)) { + return 0; + } GameString_Init(); EnumMap_Init(); @@ -200,7 +219,7 @@ void Shell_Main(void) if (!Output_Init()) { Shell_ExitSystem("Could not initialise video system"); - return; + return 1; } Screen_Init(); @@ -312,6 +331,7 @@ void Shell_Main(void) if (m_Args.level_to_play != nullptr) { Memory_FreePointer(&g_GameFlow.level_tables[GFLT_MAIN].levels[0].path); } + return 0; } void Shell_ProcessInput(void) diff --git a/src/tr2/game/render/common.c b/src/tr2/game/render/common.c index bcfb617ff..82b232443 100644 --- a/src/tr2/game/render/common.c +++ b/src/tr2/game/render/common.c @@ -45,7 +45,6 @@ static RENDERER *M_GetRenderer(void) } else if (g_Config.rendering.render_mode == RM_HARDWARE) { r = &m_Renderer_HW; } - ASSERT(r != nullptr); return r; } @@ -124,7 +123,6 @@ void Render_Init(void) void Render_Shutdown(void) { - LOG_DEBUG(""); RENDERER *const r = M_GetRenderer(); if (r != nullptr) { r->Close(r); diff --git a/src/tr2/game/shell/common.c b/src/tr2/game/shell/common.c index f7d00b73d..a1e87969b 100644 --- a/src/tr2/game/shell/common.c +++ b/src/tr2/game/shell/common.c @@ -99,7 +99,8 @@ static void M_HandleQuit(void); static void M_ConfigureOpenGL(void); static bool M_CreateGameWindow(void); -static void M_ParseArgs(SHELL_ARGS *out_args); +static void M_ShowHelp(void); +static bool M_ParseArgs(SHELL_ARGS *out_args); static void M_LoadConfig(void); static void M_HandleConfigChange(const EVENT *event, void *data); @@ -342,7 +343,16 @@ static bool M_CreateGameWindow(void) return true; } -static void M_ParseArgs(SHELL_ARGS *const out_args) +static void M_ShowHelp(void) +{ + puts("Currently available options:"); + puts(""); + puts("-g/--gold: launch The Golden Mask expansion pack."); + puts("-l/--level : launch a specific level file."); + puts("-s/--save : launch from a specific save slot (starts at 1)."); +} + +static bool M_ParseArgs(SHELL_ARGS *const out_args) { const char **args = nullptr; int32_t arg_count = 0; @@ -351,7 +361,12 @@ static void M_ParseArgs(SHELL_ARGS *const out_args) out_args->mod = M_MOD_OG; for (int32_t i = 0; i < arg_count; i++) { - if (!strcmp(args[i], "-gold")) { + if (!strcmp(args[i], "-h") || !strcmp(args[i], "--help")) { + M_ShowHelp(); + return false; + } + if (!strcmp(args[i], "-g") || !strcmp(args[i], "--gold") + || !strcmp(args[i], "-gold")) { out_args->mod = M_MOD_GM; } if ((!strcmp(args[i], "-l") || !strcmp(args[i], "--level")) @@ -366,6 +381,7 @@ static void M_ParseArgs(SHELL_ARGS *const out_args) } } } + return true; } static void M_LoadConfig(void) @@ -434,9 +450,13 @@ static void M_HandleConfigChange(const EVENT *const event, void *const data) } // TODO: refactor the hell out of me -void Shell_Main(void) +int32_t Shell_Main(void) { - M_ParseArgs(&m_Args); + if (!M_ParseArgs(&m_Args)) { + return 0; + } + + LOG_INFO("Game directory: %s", File_GetGameDirectory()); if (m_Args.mod == M_MOD_GM) { Object_Get(O_MONK_3)->setup_func = Monk3_Setup; @@ -465,7 +485,7 @@ void Shell_Main(void) if (!M_CreateGameWindow()) { Shell_ExitSystem("Failed to create game window"); - return; + return 1; } Random_Seed(); @@ -556,7 +576,7 @@ void Shell_Main(void) if (gf_cmd.action == GF_NOOP || gf_cmd.action == GF_EXIT_TO_TITLE) { Shell_ExitSystem("Title disabled & no replacement"); - return; + return 1; } } else { gf_cmd = GF_RunTitle(); @@ -578,6 +598,7 @@ void Shell_Main(void) if (m_Args.level_to_play != nullptr) { Memory_FreePointer(&g_GameFlow.level_tables[GFLT_MAIN].levels[0].path); } + return 0; } void Shell_Shutdown(void)