Skip to content

Commit

Permalink
tr1/savegame: fix crashes when changing save-slots live
Browse files Browse the repository at this point in the history
Resolves #1954.
  • Loading branch information
rr- committed Nov 25, 2024
1 parent 5d1c3d2 commit e89043b
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 20 deletions.
1 change: 1 addition & 0 deletions docs/tr1/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
- fixed invisible walls being present in front of some doors (#1948, regression from 4.6)
- fixed missing FMVs causing the game to go silent (#1931, regression from 4.6)
- fixed game crashing when toggling the bilinear filter in passport (#1942, regression from 4.5)
- fixed game crashing when changing the save slot with `/set` when in passport (#1954, regression from 4.2)

## [4.6](https://github.com/LostArtefacts/TRX/compare/tr1-4.5.1...tr1-4.6) - 2024-11-18
- added support for wading, similar to TR2+ (#1537)
Expand Down
11 changes: 9 additions & 2 deletions src/tr1/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "game/music.h"
#include "game/output.h"
#include "game/requester.h"
#include "game/savegame.h"
#include "game/shell.h"
#include "game/sound.h"
#include "global/vars.h"
Expand Down Expand Up @@ -211,6 +212,7 @@ void Config_Sanitize(void)
CLAMP(
g_Config.rendering.turbo_speed, CLOCK_TURBO_SPEED_MIN,
CLOCK_TURBO_SPEED_MAX);
CLAMPL(g_Config.maximum_save_slots, 1);
CLAMPL(g_Config.rendering.anisotropy_filter, 1.0);
CLAMP(g_Config.rendering.wireframe_width, 1.0, 100.0);

Expand All @@ -223,8 +225,13 @@ void Config_ApplyChanges(void)
{
Music_SetVolume(g_Config.music_volume);
Sound_SetMasterVolume(g_Config.sound_volume);
Requester_Shutdown(&g_SavegameRequester);
Requester_Init(&g_SavegameRequester, g_Config.maximum_save_slots);

if (Savegame_IsInitialised()) {
Savegame_Shutdown();
Savegame_Init();
Savegame_ScanSavedGames();
}

Output_ApplyRenderSettings();
}

Expand Down
3 changes: 3 additions & 0 deletions src/tr1/game/option/option_passport.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ static void M_InitSaveRequester(int16_t page_num)
} else {
req->vis_lines = 12;
}
req->vis_lines = MIN(req->max_items, req->vis_lines);

// Title screen passport is at a different pitch.
if (g_InvMode == INV_TITLE_MODE) {
Expand All @@ -298,6 +299,8 @@ static void M_RestoreSaveRequester(void)
if (g_SavegameRequester.items_used == 0) {
M_InitSaveRequester(m_PassportStatus.page);
}

CLAMPG(g_SavegameRequester.requested, g_SavegameRequester.items_used - 1);
}

static void M_InitSelectLevelRequester(void)
Expand Down
36 changes: 23 additions & 13 deletions src/tr1/game/requester.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,33 +161,43 @@ int32_t Requester_Display(REQUEST_INFO *req)
req->moredown = NULL;
}

for (int i = 0; i < line_qty; i++) {
if (!req->items[i].content) {
req->items[i].content = Text_Create(
for (int32_t i = 0; i < line_qty; i++) {
REQUESTER_ITEM *const item = &req->items[i];

const int32_t j = req->line_offset + i;
if (j < 0 || j >= req->items_used) {
Text_RemoveBackground(item->content);
Text_RemoveOutline(item->content);
continue;
}
REQUESTER_ITEM *const row_item = &req->items[j];

if (item->content == NULL && row_item->content_text != NULL) {
item->content = Text_Create(
0, line_one_off + req->line_height * i,
req->items[req->line_offset + i].content_text);
Text_CentreH(req->items[i].content, 1);
Text_AlignBottom(req->items[i].content, 1);
row_item->content_text);
Text_CentreH(item->content, 1);
Text_AlignBottom(item->content, 1);
}
if (req->line_offset + i == req->requested) {
Text_AddBackground(
req->items[i].content,
item->content,
req->pix_width - BOX_PADDING - 1 * BOX_BORDER, 0, 0, 0,
TS_REQUESTED);
Text_AddOutline(req->items[i].content, TS_REQUESTED);
Text_AddOutline(item->content, TS_REQUESTED);
} else {
Text_RemoveBackground(req->items[i].content);
Text_RemoveOutline(req->items[i].content);
Text_RemoveBackground(item->content);
Text_RemoveOutline(item->content);
}
}

if (req->line_offset != req->line_old_offset) {
for (int i = 0; i < line_qty; i++) {
if (req->items[i].content) {
REQUESTER_ITEM *const item = &req->items[i];
if (item->content != NULL) {
Text_ChangeText(
req->items[i].content,
item->content,
req->items[req->line_offset + i].content_text);
;
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/tr1/game/savegame.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ typedef struct {

void Savegame_Init(void);
void Savegame_Shutdown(void);
bool Savegame_IsInitialised(void);

void Savegame_InitCurrentInfo(void);

Expand Down
17 changes: 12 additions & 5 deletions src/tr1/game/savegame/savegame.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ typedef struct {
bool (*update_death_counters)(MYFILE *fp, GAME_INFO *game_info);
} SAVEGAME_STRATEGY;

static int32_t m_SaveSlots = 0;
static uint16_t m_NewestSlot = 0;
static SAVEGAME_INFO *m_SavegameInfo = NULL;

Expand Down Expand Up @@ -83,7 +84,7 @@ static void M_Clear(void)
return;
}

for (int i = 0; i < g_Config.maximum_save_slots; i++) {
for (int i = 0; i < m_SaveSlots; i++) {
SAVEGAME_INFO *const savegame_info = &m_SavegameInfo[i];
savegame_info->format = 0;
savegame_info->counter = -1;
Expand Down Expand Up @@ -174,8 +175,8 @@ static void M_LoadPostprocess(void)

void Savegame_Init(void)
{
m_SavegameInfo =
Memory_Alloc(sizeof(SAVEGAME_INFO) * g_Config.maximum_save_slots);
m_SaveSlots = g_Config.maximum_save_slots;
m_SavegameInfo = Memory_Alloc(sizeof(SAVEGAME_INFO) * m_SaveSlots);
}

void Savegame_Shutdown(void)
Expand All @@ -184,6 +185,11 @@ void Savegame_Shutdown(void)
Memory_FreePointer(&m_SavegameInfo);
}

bool Savegame_IsInitialised(void)
{
return m_SavegameInfo != NULL;
}

void Savegame_ProcessItemsBeforeLoad(void)
{
for (int i = 0; i < g_LevelItemCount; i++) {
Expand Down Expand Up @@ -403,7 +409,7 @@ int32_t Savegame_GetLevelNumber(const int32_t slot_num)

int32_t Savegame_GetSlotCount(void)
{
return g_Config.maximum_save_slots;
return m_SaveSlots;
}

bool Savegame_IsSlotFree(const int32_t slot_num)
Expand Down Expand Up @@ -553,7 +559,7 @@ void Savegame_ScanSavedGames(void)
g_SaveCounter = 0;
g_SavedGamesCount = 0;

for (int i = 0; i < g_Config.maximum_save_slots; i++) {
for (int i = 0; i < m_SaveSlots; i++) {
SAVEGAME_INFO *savegame_info = &m_SavegameInfo[i];
const SAVEGAME_STRATEGY *strategy = &m_Strategies[0];
while (strategy->format) {
Expand Down Expand Up @@ -598,6 +604,7 @@ void Savegame_ScanSavedGames(void)

REQUEST_INFO *req = &g_SavegameRequester;
Requester_ClearTextstrings(req);
Requester_Init(&g_SavegameRequester, Savegame_GetSlotCount());

for (int i = 0; i < req->max_items; i++) {
SAVEGAME_INFO *savegame_info = &m_SavegameInfo[i];
Expand Down

0 comments on commit e89043b

Please sign in to comment.