tr2/game-flow: slim down GAME_FLOW_LEGACY

This commit is contained in:
Marcin Kurczewski 2025-01-20 11:30:26 +01:00
parent 71f8e5a65e
commit a9c54cc628
18 changed files with 157 additions and 176 deletions

View file

@ -2,6 +2,19 @@
// NOTE: bad changes to this file may result in crashes.
// Lines starting with double slashes are comments and are ignored.
"title_replace": -1,
"title_disabled": false,
"load_save_disabled": false,
"play_any_level": false,
"lockout_option_ring": false,
"gym_enabled": true,
"demo_version": false,
"single_level": -1,
"title_track": 64,
"secret_track": 47,
"level_complete_track": 41,
"levels": [
// 0. Lara's Home
{},

View file

@ -1072,13 +1072,6 @@ typedef enum {
INV_DEATH_MODE = 5,
} INVENTORY_MODE;
typedef enum {
GAMEMODE_NOT_IN_GAME,
GAMEMODE_IN_GAME,
GAMEMODE_IN_DEMO,
GAMEMODE_IN_CUTSCENE
} GAMEMODE;
typedef enum {
TRAP_SET = 0,
TRAP_ACTIVATE = 1,

View file

@ -0,0 +1,6 @@
#include "game/game_flow/common.h"
bool GF_IsGymEnabled(void)
{
return GF_GetGymLevelNum() != -1;
}

View file

@ -20,6 +20,7 @@ typedef struct {
STATE state;
int32_t level_num;
FADER top_fader;
GAME_FLOW_COMMAND exit_gf_cmd;
} M_PRIV;
static PHASE_CONTROL M_Start(PHASE *phase);
@ -78,15 +79,11 @@ static PHASE_CONTROL M_Control(PHASE *const phase, const int32_t num_frames)
case STATE_RUN:
for (int32_t i = 0; i < num_frames; i++) {
const GAME_FLOW_COMMAND gf_cmd = Demo_Control();
if (gf_cmd.action == GF_LEVEL_COMPLETE) {
if (gf_cmd.action != GF_NOOP) {
p->state = STATE_FADE_OUT;
p->exit_gf_cmd = gf_cmd;
Fader_Init(&p->top_fader, FADER_ANY, FADER_BLACK, 0.5);
return (PHASE_CONTROL) { .action = PHASE_ACTION_NO_WAIT };
} else if (gf_cmd.action != GF_NOOP) {
return (PHASE_CONTROL) {
.action = PHASE_ACTION_END,
.gf_cmd = gf_cmd,
};
}
}
@ -104,8 +101,9 @@ static PHASE_CONTROL M_Control(PHASE *const phase, const int32_t num_frames)
case STATE_FINISH:
return (PHASE_CONTROL) {
.action = PHASE_ACTION_END,
.gf_cmd = { .action = Game_IsExiting() ? GF_EXIT_GAME
: GF_EXIT_TO_TITLE },
.gf_cmd = Game_IsExiting()
? (GAME_FLOW_COMMAND) { .action = GF_EXIT_GAME }
: p->exit_gf_cmd,
};
}

View file

@ -2,6 +2,8 @@
#include "./types.h"
bool GF_IsGymEnabled(void);
extern int32_t GF_GetLevelCount(void);
extern int32_t GF_GetDemoCount(void);
extern const char *GF_GetLevelFileName(int32_t level_num);

View file

@ -109,11 +109,12 @@ sources = [
'game/console/history.c',
'game/fader.c',
'game/game.c',
'game/game_buf.c',
'game/game_flow/common.c',
'game/game_string.c',
'game/game_string_table/common.c',
'game/game_string_table/priv.c',
'game/game_string_table/reader.c',
'game/game_buf.c',
'game/input/backends/controller.c',
'game/input/backends/internal.c',
'game/input/backends/keyboard.c',

View file

@ -68,8 +68,8 @@ GAME_FLOW_COMMAND TitleSequence(void)
return (GAME_FLOW_COMMAND) { .action = GF_EXIT_GAME };
}
if (g_GameFlowLegacy.title_track) {
Music_Play(g_GameFlowLegacy.title_track, MPM_LOOPED);
if (g_GameFlow.title_track != MX_INACTIVE) {
Music_Play(g_GameFlow.title_track, MPM_LOOPED);
}
return GF_ShowInventory(INV_TITLE_MODE);

View file

@ -62,12 +62,12 @@ void Game_Resume(void)
GAME_FLOW_COMMAND Game_Control(const bool demo_mode)
{
if (!g_GameFlowLegacy.cheat_mode_check_disabled) {
if (!g_GameFlow.cheat_keys) {
Lara_Cheat_CheckKeys();
}
if (g_LevelComplete) {
if (g_GameFlowLegacy.demo_version && g_GameFlowLegacy.single_level) {
if (g_GameFlow.is_demo_version && g_GameFlow.single_level) {
return (GAME_FLOW_COMMAND) { .action = GF_EXIT_TO_TITLE };
}
if (g_CurrentLevel == LV_GYM) {
@ -92,11 +92,11 @@ GAME_FLOW_COMMAND Game_Control(const bool demo_mode)
if (demo_mode) {
if (g_InputDB.menu_confirm || g_InputDB.menu_back) {
return (GAME_FLOW_COMMAND) { .action = GF_LEVEL_COMPLETE };
return g_GameFlow.on_demo_interrupt;
}
if (!Demo_GetInput()) {
g_Input = (INPUT_STATE) {};
return (GAME_FLOW_COMMAND) { .action = GF_LEVEL_COMPLETE };
return g_GameFlow.on_demo_end;
}
}
@ -104,14 +104,13 @@ GAME_FLOW_COMMAND Game_Control(const bool demo_mode)
|| (g_Lara.death_timer > DEATH_WAIT_INPUT && g_Input.any)
|| g_OverlayStatus == 2) {
if (demo_mode) {
return GF_TranslateScriptCommand(
g_GameFlowLegacy.on_death_demo_mode);
return g_GameFlow.on_death_demo_mode;
}
if (g_CurrentLevel == LV_GYM) {
return (GAME_FLOW_COMMAND) { .action = GF_EXIT_TO_TITLE };
}
if (g_GameFlowLegacy.on_death_in_game) {
return GF_TranslateScriptCommand(g_GameFlowLegacy.on_death_in_game);
if (g_GameFlow.on_death_in_game.action != GF_NOOP) {
return g_GameFlow.on_death_in_game;
}
if (g_OverlayStatus == 2) {
g_OverlayStatus = 1;
@ -128,7 +127,7 @@ GAME_FLOW_COMMAND Game_Control(const bool demo_mode)
|| g_OverlayStatus <= 0)
&& g_Lara.death_timer == 0 && !g_Lara.extra_anim) {
if (g_OverlayStatus > 0) {
if (g_GameFlowLegacy.load_save_disabled) {
if (g_GameFlow.load_save_disabled) {
g_OverlayStatus = 0;
} else if (g_Input.load) {
g_OverlayStatus = -1;
@ -245,7 +244,7 @@ void Game_ProcessInput(void)
Lara_UseItem(O_LARGE_MEDIPACK_OPTION);
}
if (g_GameFlowLegacy.load_save_disabled) {
if (g_GameFlow.load_save_disabled) {
g_Input.save = 0;
g_Input.load = 0;
}

View file

@ -15,6 +15,8 @@
#include <libtrx/virtual_file.h>
#define GF_CURRENT_VERSION 3
#define GF_DESCRIPTION_SIZE 256
#define GF_EXPECTED_SIZE 128
static int16_t m_LevelOffsets[200] = {};
static int16_t *m_SequenceBuf = NULL;
@ -22,11 +24,12 @@ static int16_t *m_ScriptTable[MAX_LEVELS] = {};
static int16_t *m_FrontendSequence = NULL;
static void M_ReadStringTable(
VFILE *file, int32_t count, char ***table, char **buffer);
VFILE *file, int32_t count, char ***table, char **buffer,
uint8_t cypher_code);
static void M_ReadStringTable(
VFILE *const file, const int32_t count, char ***const table,
char **const buffer)
char **const buffer, const uint8_t cypher_code)
{
VFile_Read(file, m_LevelOffsets, sizeof(int16_t) * count);
@ -35,10 +38,8 @@ static void M_ReadStringTable(
*buffer = Memory_Alloc(buf_size);
VFile_Read(file, *buffer, buf_size);
if (g_GameFlowLegacy.cyphered_strings) {
for (int32_t i = 0; i < buf_size; i++) {
(*buffer)[i] ^= g_GameFlowLegacy.cypher_code;
}
for (int32_t i = 0; i < buf_size; i++) {
(*buffer)[i] ^= cypher_code;
}
if (table != NULL) {
@ -70,69 +71,40 @@ bool GF_LoadFromFile(const char *const file_name)
return false;
}
char description[256];
VFile_Read(file, description, 256);
char description[GF_DESCRIPTION_SIZE];
VFile_Read(file, description, GF_DESCRIPTION_SIZE);
if (VFile_ReadS16(file) != sizeof(GAME_FLOW_LEGACY)) {
if (VFile_ReadS16(file) != GF_EXPECTED_SIZE) {
return false;
}
g_GameFlowLegacy.first_option = VFile_ReadS32(file);
g_GameFlowLegacy.title_replace = VFile_ReadS32(file);
g_GameFlowLegacy.on_death_demo_mode = VFile_ReadS32(file);
g_GameFlowLegacy.on_death_in_game = VFile_ReadS32(file);
g_GameFlowLegacy.no_input_time = VFile_ReadS32(file);
g_GameFlowLegacy.on_demo_interrupt = VFile_ReadS32(file);
g_GameFlowLegacy.on_demo_end = VFile_ReadS32(file);
VFile_Skip(file, 36);
VFile_Skip(file, 64);
g_GameFlowLegacy.num_levels = VFile_ReadU16(file);
g_GameFlowLegacy.num_pictures = VFile_ReadU16(file);
g_GameFlowLegacy.num_titles = VFile_ReadU16(file);
g_GameFlowLegacy.num_fmvs = VFile_ReadU16(file);
g_GameFlowLegacy.num_cutscenes = VFile_ReadU16(file);
const uint16_t num_pictures = VFile_ReadU16(file);
const uint16_t num_titles = VFile_ReadU16(file);
const uint16_t num_fmvs = VFile_ReadU16(file);
const uint16_t num_cutscenes = VFile_ReadU16(file);
g_GameFlowLegacy.num_demos = VFile_ReadU16(file);
g_GameFlowLegacy.title_track = VFile_ReadU16(file);
g_GameFlowLegacy.single_level = VFile_ReadS16(file);
VFile_Skip(file, 32);
VFile_Skip(file, 44);
const uint16_t flags = VFile_ReadU16(file);
// clang-format off
g_GameFlowLegacy.demo_version = flags & 0x0001 ? 1 : 0;
g_GameFlowLegacy.title_disabled = flags & 0x0002 ? 1 : 0;
g_GameFlowLegacy.cheat_mode_check_disabled = flags & 0x0004 ? 1 : 0;
g_GameFlowLegacy.load_save_disabled = flags & 0x0010 ? 1 : 0;
g_GameFlowLegacy.screen_sizing_disabled = flags & 0x0020 ? 1 : 0;
g_GameFlowLegacy.lockout_option_ring = flags & 0x0040 ? 1 : 0;
g_GameFlowLegacy.dozy_cheat_enabled = flags & 0x0080 ? 1 : 0;
g_GameFlowLegacy.cyphered_strings = flags & 0x0100 ? 1 : 0;
g_GameFlowLegacy.gym_enabled = flags & 0x0200 ? 1 : 0;
g_GameFlowLegacy.play_any_level = flags & 0x0400 ? 1 : 0;
g_GameFlowLegacy.cheat_enable = flags & 0x0800 ? 1 : 0;
// clang-format on
VFile_Skip(file, 6);
g_GameFlowLegacy.cypher_code = VFile_ReadU8(file);
g_GameFlowLegacy.language = VFile_ReadU8(file);
g_GameFlowLegacy.secret_track = VFile_ReadU8(file);
g_GameFlowLegacy.level_complete_track = VFile_ReadU8(file);
VFile_Skip(file, 4);
const uint8_t cypher_code = VFile_ReadU8(file);
VFile_Skip(file, 7);
g_GF_LevelNames =
Memory_Alloc(sizeof(char *) * g_GameFlowLegacy.num_levels);
M_ReadStringTable(file, g_GameFlowLegacy.num_levels, NULL, NULL);
M_ReadStringTable(file, g_GameFlowLegacy.num_levels, NULL, NULL, 0);
// picture filename strings
M_ReadStringTable(file, g_GameFlowLegacy.num_pictures, NULL, NULL);
M_ReadStringTable(file, num_pictures, NULL, NULL, 0);
M_ReadStringTable(
file, g_GameFlowLegacy.num_titles, &g_GF_TitleFileNames,
&g_GF_TitleFileNamesBuf);
file, num_titles, &g_GF_TitleFileNames, &g_GF_TitleFileNamesBuf,
cypher_code);
M_ReadStringTable(
file, g_GameFlowLegacy.num_fmvs, &g_GF_FMVFilenames,
&g_GF_FMVFilenamesBuf);
file, num_fmvs, &g_GF_FMVFilenames, &g_GF_FMVFilenamesBuf, cypher_code);
M_ReadStringTable(
file, g_GameFlowLegacy.num_levels, &g_GF_LevelFileNames,
&g_GF_LevelFileNamesBuf);
&g_GF_LevelFileNamesBuf, cypher_code);
M_ReadStringTable(
file, g_GameFlowLegacy.num_cutscenes, &g_GF_CutsceneFileNames,
&g_GF_CutsceneFileNamesBuf);
file, num_cutscenes, &g_GF_CutsceneFileNames,
&g_GF_CutsceneFileNamesBuf, cypher_code);
VFile_Read(
file, &m_LevelOffsets,
@ -151,29 +123,6 @@ bool GF_LoadFromFile(const char *const file_name)
VFile_Read(
file, g_GF_ValidDemos, sizeof(int16_t) * g_GameFlowLegacy.num_demos);
// game strings
if (VFile_ReadS16(file) != 89) {
return false;
}
M_ReadStringTable(file, 89, NULL, NULL);
// pc strings
M_ReadStringTable(file, 41, NULL, NULL);
// puzzle 1-4 strings
M_ReadStringTable(file, g_GameFlowLegacy.num_levels, NULL, NULL);
M_ReadStringTable(file, g_GameFlowLegacy.num_levels, NULL, NULL);
M_ReadStringTable(file, g_GameFlowLegacy.num_levels, NULL, NULL);
M_ReadStringTable(file, g_GameFlowLegacy.num_levels, NULL, NULL);
// pickup 1-2 strings
M_ReadStringTable(file, g_GameFlowLegacy.num_levels, NULL, NULL);
M_ReadStringTable(file, g_GameFlowLegacy.num_levels, NULL, NULL);
// key 1-4 strings
M_ReadStringTable(file, g_GameFlowLegacy.num_levels, NULL, NULL);
M_ReadStringTable(file, g_GameFlowLegacy.num_levels, NULL, NULL);
M_ReadStringTable(file, g_GameFlowLegacy.num_levels, NULL, NULL);
M_ReadStringTable(file, g_GameFlowLegacy.num_levels, NULL, NULL);
VFile_Close(file);
Benchmark_End(benchmark, NULL);
return true;
@ -186,8 +135,6 @@ bool GF_LoadScriptFile(const char *const fname)
if (!GF_LoadFromFile(fname)) {
return false;
}
g_GameFlowLegacy.level_complete_track = MX_END_OF_LEVEL;
return true;
}
@ -213,7 +160,7 @@ GAME_FLOW_COMMAND GF_DoLevelSequence(
const GAME_FLOW_COMMAND gf_cmd = GF_InterpretSequence(ptr, type);
current_level++;
if (g_GameFlowLegacy.single_level >= 0) {
if (g_GameFlow.single_level >= 0) {
return gf_cmd;
}
if (gf_cmd.action != GF_LEVEL_COMPLETE) {
@ -298,7 +245,9 @@ GAME_FLOW_COMMAND GF_InterpretSequence(
START_INFO *const start = &g_SaveGame.start[g_CurrentLevel];
start->stats = g_SaveGame.current_stats;
Music_Play(g_GameFlowLegacy.level_complete_track, MPM_ALWAYS);
if (g_GameFlow.level_complete_track != MX_INACTIVE) {
Music_Play(g_GameFlow.level_complete_track, MPM_ALWAYS);
}
PHASE *const stats_phase =
Phase_Stats_Create((PHASE_STATS_ARGS) {
.background_type = BK_OBJECT,

View file

@ -33,7 +33,7 @@ void GF_SetLevelTitle(const int32_t level_num, const char *const title)
int32_t GF_GetGymLevelNum(void)
{
return g_GameFlowLegacy.gym_enabled ? LV_GYM : -1;
return g_GameFlow.gym_enabled ? LV_GYM : -1;
}
void GF_OverrideCommand(const GAME_FLOW_COMMAND command)

View file

@ -1 +1,3 @@
#pragma once
#include <libtrx/game/game_flow/common.h>

View file

@ -1,5 +1,6 @@
#include "game/game_flow/reader.h"
#include "game/game_flow.h"
#include "game/game_flow/common.h"
#include "game/game_flow/vars.h"
#include "global/vars.h"
@ -13,6 +14,7 @@ static void M_LoadGlobalInjections(JSON_OBJECT *obj, GAME_FLOW *gf);
static void M_LoadLevelInjections(
JSON_OBJECT *obj, const GAME_FLOW *gf, GAME_FLOW_LEVEL *level);
static bool M_LoadScriptLevels(JSON_OBJECT *obj, GAME_FLOW *gf);
static bool M_LoadGlobal(JSON_OBJECT *obj, GAME_FLOW *gf);
static void M_LoadGlobalInjections(JSON_OBJECT *const obj, GAME_FLOW *const gf)
{
@ -114,6 +116,42 @@ end:
return result;
}
static bool M_LoadGlobal(JSON_OBJECT *const obj, GAME_FLOW *const gf)
{
gf->title_replace =
GF_TranslateScriptCommand(JSON_ObjectGetInt(obj, "title_replace", -1));
gf->first_option = GF_TranslateScriptCommand(
JSON_ObjectGetInt(obj, "first_option", 0x500));
gf->on_death_demo_mode = GF_TranslateScriptCommand(
JSON_ObjectGetInt(obj, "on_death_demo_mode", 0x500));
gf->on_death_in_game = GF_TranslateScriptCommand(
JSON_ObjectGetInt(obj, "on_death_in_game", -1));
gf->demo_delay = JSON_ObjectGetInt(obj, "demo_delay", 30);
gf->on_demo_interrupt = GF_TranslateScriptCommand(
JSON_ObjectGetInt(obj, "on_demo_interrupt", 0x500));
gf->on_demo_end =
GF_TranslateScriptCommand(JSON_ObjectGetInt(obj, "on_demo_end", 0x500));
gf->is_demo_version = JSON_ObjectGetBool(obj, "demo_version", false);
gf->title_disabled = JSON_ObjectGetBool(obj, "title_disabled", false);
// clang-format off
gf->load_save_disabled = JSON_ObjectGetBool(obj, "load_save_disabled", false);
gf->cheat_keys = JSON_ObjectGetBool(obj, "cheat_keys", true);
gf->lockout_option_ring = JSON_ObjectGetBool(obj, "lockout_option_ring", true);
gf->play_any_level = JSON_ObjectGetBool(obj, "play_any_level", false);
gf->gym_enabled = JSON_ObjectGetBool(obj, "gym_enabled", true);
gf->single_level = JSON_ObjectGetInt(obj, "single_level", -1);
// clang-format on
gf->title_track = JSON_ObjectGetInt(obj, "title_track", MX_INACTIVE);
gf->secret_track = JSON_ObjectGetInt(obj, "secret_track", MX_INACTIVE);
gf->level_complete_track =
JSON_ObjectGetInt(obj, "level_complete_track", MX_INACTIVE);
return true;
}
bool GF_N_Load(const char *const path)
{
GF_N_Shutdown();
@ -144,6 +182,7 @@ bool GF_N_Load(const char *const path)
GAME_FLOW *const gf = &g_GameFlow;
JSON_OBJECT *root_obj = JSON_ValueAsObject(root);
M_LoadGlobalInjections(root_obj, gf);
result &= M_LoadGlobal(root_obj, gf);
result &= M_LoadScriptLevels(root_obj, gf);
end:

View file

@ -1,5 +1,6 @@
#pragma once
#include "game/music.h"
#include "global/types.h"
typedef struct {
@ -22,4 +23,25 @@ typedef struct {
int32_t level_count;
GAME_FLOW_LEVEL *levels;
INJECTION_DATA injections;
GAME_FLOW_COMMAND first_option;
GAME_FLOW_COMMAND title_replace;
GAME_FLOW_COMMAND on_death_demo_mode;
GAME_FLOW_COMMAND on_death_in_game;
GAME_FLOW_COMMAND on_demo_interrupt;
GAME_FLOW_COMMAND on_demo_end;
float demo_delay;
bool is_demo_version;
bool title_disabled;
bool play_any_level;
bool gym_enabled;
bool lockout_option_ring;
bool cheat_keys;
bool load_save_disabled;
int32_t single_level;
MUSIC_TRACK_ID title_track;
MUSIC_TRACK_ID secret_track;
MUSIC_TRACK_ID level_complete_track;
} GAME_FLOW;

View file

@ -202,7 +202,7 @@ static GAME_FLOW_COMMAND M_Finish(
// second passport page:
if (ring->mode == INV_TITLE_MODE) {
// title mode - new game or select level.
if (g_GameFlowLegacy.play_any_level) {
if (g_GameFlow.play_any_level) {
return (GAME_FLOW_COMMAND) {
.action = GF_START_GAME,
.param = g_Inv_ExtraData[1] + 1,
@ -249,7 +249,7 @@ static GAME_FLOW_COMMAND M_Finish(
break;
case O_PHOTO_OPTION:
if (g_GameFlowLegacy.gym_enabled) {
if (GF_IsGymEnabled()) {
return (GAME_FLOW_COMMAND) {
.action = GF_START_GAME,
.param = LV_GYM,
@ -335,7 +335,7 @@ static GAME_FLOW_COMMAND M_Control(INV_RING *const ring)
} else if (
g_GameFlowLegacy.num_demos > 0 && ring->motion.status == RNG_OPEN) {
m_NoInputCounter++;
if (m_NoInputCounter > g_GameFlowLegacy.no_input_time) {
if (m_NoInputCounter > g_GameFlow.demo_delay * LOGIC_FPS) {
ring->is_demo_needed = true;
}
}
@ -505,7 +505,7 @@ static GAME_FLOW_COMMAND M_Control(INV_RING *const ring)
g_InputDB = (INPUT_STATE) {};
} else if (ring->type == RT_MAIN) {
if (g_InvRing_Source[RT_OPTION].count > 0
&& !g_GameFlowLegacy.lockout_option_ring) {
&& !InvRing_IsOptionLockedOut()) {
InvRing_MotionSetup(ring, RNG_CLOSING, RNG_MAIN2OPTION, 24);
InvRing_MotionRadius(ring, 0);
InvRing_MotionRotation(
@ -764,7 +764,7 @@ INV_RING *InvRing_Open(const INVENTORY_MODE mode)
if (mode == INV_TITLE_MODE) {
g_InvRing_Source[RT_OPTION].count = TITLE_RING_OBJECTS;
if (g_GameFlowLegacy.gym_enabled) {
if (GF_IsGymEnabled()) {
g_InvRing_Source[RT_OPTION].count++;
}
InvRing_ShowVersionText();
@ -786,9 +786,7 @@ INV_RING *InvRing_Open(const INVENTORY_MODE mode)
}
g_InvRing_Source[RT_OPTION].current = 0;
if (g_GymInvOpenEnabled && mode == INV_TITLE_MODE
&& !g_GameFlowLegacy.load_save_disabled
&& g_GameFlowLegacy.gym_enabled) {
if (g_GymInvOpenEnabled && mode == INV_TITLE_MODE && GF_IsGymEnabled()) {
for (int32_t i = 0; i < g_InvRing_Source[RT_OPTION].count; i++) {
if (g_InvRing_Source[RT_OPTION].items[i]->object_id
== O_PHOTO_OPTION) {
@ -905,5 +903,5 @@ GAME_FLOW_COMMAND InvRing_Control(
bool InvRing_IsOptionLockedOut(void)
{
return g_GameFlowLegacy.lockout_option_ring;
return g_GameFlow.lockout_option_ring;
}

View file

@ -1,5 +1,6 @@
#include "decomp/decomp.h"
#include "decomp/savegame.h"
#include "game/game_flow.h"
#include "game/game_string.h"
#include "game/input.h"
#include "game/inventory_ring.h"
@ -26,14 +27,14 @@ void Option_Passport_Control(INVENTORY_ITEM *const item)
const int32_t page = frame % 5 == 0 ? frame / 5 : -1;
if (g_Inv_Mode == INV_LOAD_MODE || g_Inv_Mode == INV_SAVE_MODE
|| g_GameFlowLegacy.load_save_disabled) {
|| g_GameFlow.load_save_disabled) {
g_InputDB.menu_left = 0;
g_InputDB.menu_right = 0;
}
switch (page) {
case 0:
if (g_GameFlowLegacy.load_save_disabled) {
if (g_GameFlow.load_save_disabled) {
g_InputDB = (INPUT_STATE) { .menu_right = 1 };
break;
}
@ -81,7 +82,7 @@ void Option_Passport_Control(INVENTORY_ITEM *const item)
break;
case 1:
if (g_GameFlowLegacy.load_save_disabled) {
if (g_GameFlow.load_save_disabled) {
g_InputDB = (INPUT_STATE) { .menu_right = 1 };
break;
}
@ -146,7 +147,7 @@ void Option_Passport_Control(INVENTORY_ITEM *const item)
m_PassportMode = PASSPORT_MODE_LOAD_GAME;
g_Input = (INPUT_STATE) {};
g_InputDB = (INPUT_STATE) {};
} else if (g_GameFlowLegacy.play_any_level) {
} else if (g_GameFlow.play_any_level) {
Text_Remove(m_LevelText);
m_LevelText = NULL;
@ -169,7 +170,7 @@ void Option_Passport_Control(INVENTORY_ITEM *const item)
if (g_PasswordText1 == NULL) {
if (g_Inv_Mode == INV_TITLE_MODE) {
g_PasswordText1 = Text_Create(0, -16, GS(PASSPORT_EXIT_GAME));
} else if (g_GameFlowLegacy.demo_version) {
} else if (g_GameFlow.is_demo_version) {
g_PasswordText1 = Text_Create(0, -16, GS(PASSPORT_EXIT_DEMO));
} else {
g_PasswordText1 =

View file

@ -3,6 +3,7 @@
#include "decomp/decomp.h"
#include "game/clock.h"
#include "game/game.h"
#include "game/game_flow.h"
#include "game/inventory.h"
#include "game/music.h"
#include "game/objects/common.h"
@ -522,7 +523,7 @@ void Overlay_AddDisplayPickup(const GAME_OBJECT_ID object_id)
{
if (object_id == O_SECRET_1 || object_id == O_SECRET_2
|| object_id == O_SECRET_3) {
Music_Play(g_GameFlowLegacy.secret_track, MPM_ALWAYS);
Music_Play(g_GameFlow.secret_track, MPM_ALWAYS);
}
int32_t grid_x = -1;

View file

@ -393,16 +393,16 @@ void Shell_Main(void)
return;
}
GAME_FLOW_COMMAND gf_cmd =
GF_TranslateScriptCommand(g_GameFlowLegacy.first_option);
GAME_FLOW_COMMAND gf_cmd = g_GameFlow.first_option;
bool is_loop_continued = true;
while (is_loop_continued) {
LOG_DEBUG("action=%d param=%x", gf_cmd.action, gf_cmd.param);
switch (gf_cmd.action) {
case GF_START_GAME:
case GF_SELECT_GAME:
if (g_GameFlowLegacy.single_level >= 0) {
gf_cmd = GF_DoLevelSequence(
g_GameFlowLegacy.single_level, GFL_NORMAL);
if (g_GameFlow.single_level >= 0) {
gf_cmd =
GF_DoLevelSequence(g_GameFlow.single_level, GFL_NORMAL);
} else {
if (gf_cmd.param > g_GameFlowLegacy.num_levels) {
Shell_ExitSystemFmt(
@ -442,13 +442,11 @@ void Shell_Main(void)
break;
case GF_EXIT_TO_TITLE:
if (g_GameFlowLegacy.title_disabled) {
gf_cmd =
GF_TranslateScriptCommand(g_GameFlowLegacy.title_replace);
if (g_GameFlow.title_disabled) {
gf_cmd = g_GameFlow.title_replace;
if (gf_cmd.action == GF_NOOP
|| gf_cmd.action == GF_EXIT_TO_TITLE) {
Shell_ExitSystem(
"GameMain Failed: Title disabled & no replacement");
Shell_ExitSystem("Title disabled & no replacement");
return;
}
} else {

View file

@ -303,13 +303,6 @@ typedef struct {
uint8_t palette_index;
} NAMED_COLOR;
typedef enum {
GAMEMODE_NOT_IN_GAME,
GAMEMODE_IN_GAME,
GAMEMODE_IN_DEMO,
GAMEMODE_IN_CUTSCENE
} GAMEMODE;
typedef enum {
TRAP_SET = 0,
TRAP_ACTIVATE = 1,
@ -318,42 +311,8 @@ typedef enum {
} TRAP_ANIM;
typedef struct {
int32_t first_option;
int32_t title_replace;
int32_t on_death_demo_mode;
int32_t on_death_in_game;
int32_t no_input_time;
int32_t on_demo_interrupt;
int32_t on_demo_end;
uint16_t reserved1[18];
uint16_t num_levels;
uint16_t num_pictures;
uint16_t num_titles;
uint16_t num_fmvs;
uint16_t num_cutscenes;
uint16_t num_demos;
uint16_t title_track;
int16_t single_level;
uint16_t reserved2[16];
uint16_t demo_version: 1;
uint16_t title_disabled: 1;
uint16_t cheat_mode_check_disabled: 1;
uint16_t load_save_disabled: 1;
uint16_t screen_sizing_disabled: 1;
uint16_t lockout_option_ring: 1;
uint16_t dozy_cheat_enabled: 1;
uint16_t cyphered_strings: 1;
uint16_t gym_enabled: 1;
uint16_t play_any_level: 1;
uint16_t cheat_enable: 1;
uint16_t reserved3[3];
uint8_t cypher_code;
uint8_t language;
uint8_t secret_track;
uint8_t level_complete_track;
uint16_t reserved4[2];
} GAME_FLOW_LEGACY;
typedef enum {