tr2/shell: add -l argument support

This commit is contained in:
Marcin Kurczewski 2025-03-11 11:53:17 +01:00
parent 1336767f06
commit c2a930a1cb
16 changed files with 123 additions and 78 deletions

View file

@ -1,8 +1 @@
{
"levels": [
// Level 0: Lara's Home
{
"title": "Test Level",
},
]
}
{"levels": [{"title": "Test Level"}]}

View file

@ -0,0 +1,33 @@
{
// This file is used to enable the -l argument support.
"cmd_init": {"action": "exit_to_title"},
"cmd_title": {"action": "noop"},
"cmd_death_in_demo": {"action": "exit_to_title"},
"cmd_death_in_game": {"action": "noop"},
"cmd_demo_interrupt": {"action": "exit_to_title"},
"cmd_demo_end": {"action": "exit_to_title"},
"cheat_keys": true,
"load_save_disabled": false,
"play_any_level": false,
"lockout_option_ring": false,
"gym_enabled": true,
"demo_version": false,
"single_level": 0,
"demo_delay": 30,
"secret_track": 47,
"levels": [
{
"path": "PLACEHOLDER",
"music_track": -1,
"sequence": [
{"type": "set_secret_count", "count": 0},
{"type": "loop_game"},
{"type": "level_stats"},
],
},
],
}

View file

@ -0,0 +1 @@
{"levels": [{"title": "Test Level"}]}

View file

@ -4,6 +4,7 @@
- added a `/cheats` console command
- added a `/wireframe` console command (#2500)
- added a `/fps` console command
- added support for `-l`/`--level` argument to play a single level
- fixed smashed windows blocking enemy pathing after loading a save (#2535)
- fixed several instances of the camera going out of bounds (#1034)
- fixed Lara getting stuck in a T-pose after jumping/falling and then dying before reaching fast fall speed (#2575)

View file

@ -0,0 +1,33 @@
#include "filesystem.h"
#include "game/shell.h"
#include "log.h"
#include "memory.h"
#include "utils.h"
#include <string.h>
static int m_ArgCount = 0;
static const char **m_ArgStrings = nullptr;
void Shell_GetCommandLine(int *arg_count, const char ***args)
{
*arg_count = m_ArgCount;
*args = m_ArgStrings;
}
int main(int argc, char *argv[])
{
char *log_path = File_GetFullPath(PROJECT_NAME ".log");
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;
}

View file

@ -7,10 +7,12 @@ extern void Shell_Shutdown(void);
extern SDL_Window *Shell_GetWindow(void);
void Shell_Setup(void);
extern void Shell_Main(void);
void Shell_Terminate(int32_t exit_code);
void Shell_ExitSystem(const char *message);
void Shell_ExitSystemFmt(const char *fmt, ...);
void Shell_GetCommandLine(int *arg_count, const char ***args);
void Shell_ScheduleExit(void);
bool Shell_IsExiting(void);

View file

@ -24,6 +24,7 @@ build_opts = [
'-Wno-gnu-zero-variadic-macro-arguments',
'-DMESON_BUILD',
'-DGLEW_NO_GLU',
'-DSDL_MAIN_HANDLED',
'-fms-extensions',
'-fno-omit-frame-pointer',
# end of common options
@ -167,6 +168,7 @@ sources = [
'game/rooms/draw.c',
'game/savegame.c',
'game/shell/common.c',
'game/shell/main.c',
'game/sound.c',
'game/text.c',
'game/ui/common.c',

View file

@ -137,9 +137,9 @@ void Shell_Main(void)
const char *level_to_play = nullptr;
char **args = nullptr;
const char **args = nullptr;
int32_t arg_count = 0;
S_Shell_GetCommandLine(&arg_count, &args);
Shell_GetCommandLine(&arg_count, &args);
for (int32_t i = 0; i < arg_count; i++) {
if (!strcmp(args[i], "-gold")) {
m_ActiveMod = M_MOD_UB;
@ -284,10 +284,6 @@ void Shell_Main(void)
if (level_to_play != nullptr) {
Memory_FreePointer(&g_GameFlow.level_tables[GFLT_MAIN].levels[0].path);
}
for (int i = 0; i < arg_count; i++) {
Memory_FreePointer(&args[i]);
}
Memory_FreePointer(&args);
}
void Shell_ProcessInput(void)

View file

@ -1,5 +1,3 @@
#pragma once
#include <libtrx/game/shell.h>
void Shell_Main(void);

View file

@ -28,6 +28,7 @@ build_opts = [
'-Wno-gnu-zero-variadic-macro-arguments',
'-DMESON_BUILD',
'-DGLEW_NO_GLU',
'-DSDL_MAIN_HANDLED',
'-fms-extensions',
'-fno-omit-frame-pointer',
# end of common options

View file

@ -9,6 +9,7 @@
#include "game/sound.h"
#include <libtrx/config.h>
#include <libtrx/debug.h>
#include <libtrx/filesystem.h>
#include <libtrx/game/ui/common.h>
#include <libtrx/gfx/common.h>
@ -16,10 +17,6 @@
#include <libtrx/log.h>
#include <libtrx/memory.h>
#define SDL_MAIN_HANDLED
#include <libtrx/debug.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_error.h>
#include <SDL2/SDL_events.h>
@ -34,8 +31,6 @@
#include <string.h>
#include <time.h>
static int m_ArgCount = 0;
static char **m_ArgStrings = nullptr;
static SDL_Window *m_Window = nullptr;
static void M_HandleQuit(void);
@ -223,23 +218,6 @@ void Shell_ProcessEvents(void)
}
}
int main(int argc, char **argv)
{
char *log_path = File_GetFullPath("TR1X.log");
Log_Init(log_path);
Memory_FreePointer(&log_path);
LOG_INFO("Game directory: %s", File_GetGameDirectory());
m_ArgCount = argc;
m_ArgStrings = argv;
Shell_Setup();
Shell_Main();
Shell_Terminate(0);
return 0;
}
static void M_SetGLBackend(const GFX_GL_BACKEND backend)
{
switch (backend) {
@ -302,17 +280,6 @@ void S_Shell_CreateWindow(void)
Shell_ExitSystem("System Error: cannot attach opengl context");
}
bool S_Shell_GetCommandLine(int *arg_count, char ***args)
{
*arg_count = m_ArgCount;
*args = Memory_Alloc(m_ArgCount * sizeof(char *));
for (int i = 0; i < m_ArgCount; i++) {
(*args)[i] = Memory_Alloc(strlen(m_ArgStrings[i]) + 1);
strcpy((*args)[i], m_ArgStrings[i]);
}
return true;
}
SDL_Window *Shell_GetWindow(void)
{
return m_Window;

View file

@ -4,6 +4,5 @@
void S_Shell_Init(void);
void S_Shell_CreateWindow(void);
bool S_Shell_GetCommandLine(int *arg_count, char ***args);
void S_Shell_ToggleFullscreen(void);
void S_Shell_HandleWindowResize(void);

View file

@ -33,9 +33,27 @@
#include <stdarg.h>
#include <stdio.h>
typedef enum {
M_MOD_UNKNOWN,
M_MOD_OG,
M_MOD_CUSTOM_LEVEL,
} M_MOD;
static struct {
char *game_flow_path;
char *game_strings_path;
} m_ModPaths[] = {
[M_MOD_OG] = {
.game_flow_path = "cfg/TR2X_gameflow.json5",
.game_strings_path = "cfg/TR2X_strings.json5",
},
[M_MOD_CUSTOM_LEVEL] = {
.game_flow_path = "cfg/TR2X_gameflow_level.json5",
.game_strings_path = "cfg/TR2X_strings_level.json5",
},
};
static M_MOD m_ActiveMod = M_MOD_UNKNOWN;
static Uint64 m_UpdateDebounce = 0;
static const char *m_CurrentGameFlowPath = "cfg/TR2X_gameflow.json5";
static const char *m_CurrentGameStringsPath = "cfg/TR2X_strings.json5";
static void M_SyncToWindow(void);
static void M_SyncFromWindow(void);
@ -320,6 +338,21 @@ static void M_HandleConfigChange(const EVENT *const event, void *const data)
// TODO: refactor the hell out of me
void Shell_Main(void)
{
m_ActiveMod = M_MOD_OG;
const char *level_to_play = nullptr;
const char **args = nullptr;
int32_t arg_count = 0;
Shell_GetCommandLine(&arg_count, &args);
for (int32_t i = 0; i < arg_count; i++) {
if ((!strcmp(args[i], "-l") || !strcmp(args[i], "--level"))
&& i + 1 < arg_count) {
level_to_play = args[i + 1];
m_ActiveMod = M_MOD_CUSTOM_LEVEL;
}
}
GameString_Init();
EnumMap_Init();
Config_Init();
@ -349,8 +382,8 @@ void Shell_Main(void)
Render_Reset(RENDER_RESET_PARAMS);
GF_Init();
GF_LoadFromFile(m_CurrentGameFlowPath);
GameStringTable_LoadFromFile(m_CurrentGameStringsPath);
GF_LoadFromFile(m_ModPaths[m_ActiveMod].game_flow_path);
GameStringTable_LoadFromFile(m_ModPaths[m_ActiveMod].game_strings_path);
GameStringTable_Apply(nullptr);
Savegame_Init();
@ -359,7 +392,13 @@ void Shell_Main(void)
GameBuf_Init();
GF_COMMAND gf_cmd = GF_DoFrontendSequence();
if (level_to_play != nullptr) {
g_GameFlow.level_tables[GFLT_MAIN].levels[0].path = level_to_play;
}
GF_COMMAND gf_cmd = level_to_play != nullptr
? (GF_COMMAND) { .action = GF_START_GAME, .param = 0 }
: GF_DoFrontendSequence();
bool loop_continue = !Shell_IsExiting();
while (loop_continue) {
LOG_INFO(
@ -451,7 +490,7 @@ const char *Shell_GetConfigPath(void)
const char *Shell_GetGameFlowPath(void)
{
return m_CurrentGameFlowPath;
return m_ModPaths[m_ActiveMod].game_flow_path;
}
void Shell_Start(void)

View file

@ -4,7 +4,6 @@
#include <libtrx/game/shell.h>
void Shell_Main(void);
void Shell_Start();
void Shell_ProcessEvents(void);

View file

@ -1,19 +0,0 @@
#include "decomp/decomp.h"
#include "game/shell.h"
#include "global/vars.h"
#include <libtrx/filesystem.h>
#include <libtrx/log.h>
#include <libtrx/memory.h>
int main(int argc, char **argv)
{
char *log_path = File_GetFullPath("TR2X.log");
Log_Init(log_path);
Memory_Free(log_path);
Shell_Setup();
Shell_Main();
Shell_Terminate(0);
return 0;
}

View file

@ -28,6 +28,7 @@ build_opts = [
'-Wno-gnu-zero-variadic-macro-arguments',
'-DMESON_BUILD',
'-DGLEW_NO_GLU',
'-DSDL_MAIN_HANDLED',
'-fms-extensions',
'-fno-omit-frame-pointer',
# end of common options
@ -286,7 +287,6 @@ sources = [
'game/viewport.c',
'global/enum_map.c',
'global/vars.c',
'main.c',
resources,
]