tr1/savegame: fix crashes when changing save-slots live

Resolves #1954.
This commit is contained in:
Marcin Kurczewski 2024-11-25 16:27:07 +01:00
parent 5b928426e1
commit 0ff682b352
No known key found for this signature in database
GPG key ID: CC65E6FD28CAE42A
6 changed files with 50 additions and 23 deletions

View file

@ -3,6 +3,7 @@
- fixed big font scale causing text overlaps in the graphics options (#1946)
- 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)

View file

@ -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"
@ -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);
@ -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();
}

View file

@ -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) {
@ -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)

View file

@ -161,33 +161,41 @@ 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(
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);
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, 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,
req->pix_width - BOX_PADDING - 1 * BOX_BORDER, 0, 0, 0,
TS_REQUESTED);
Text_AddOutline(req->items[i].content, TS_REQUESTED);
item->content, req->pix_width - BOX_PADDING - 1 * BOX_BORDER, 0,
0, 0, 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);
;
}
}
}

View file

@ -48,6 +48,7 @@ typedef struct {
void Savegame_Init(void);
void Savegame_Shutdown(void);
bool Savegame_IsInitialised(void);
void Savegame_InitCurrentInfo(void);

View file

@ -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;
@ -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;
@ -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)
@ -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++) {
@ -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)
@ -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) {
@ -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];