tr2/output: fix crashes in large rooms
Some checks are pending
Run code linters / Run code linters (push) Waiting to run
Publish a pre-release / Build TR1 (push) Has been skipped
Publish a pre-release / Build TR2 (push) Has been skipped
Publish a pre-release / Create a prerelease (push) Has been skipped

Resolves #2749.
This commit is contained in:
Marcin Kurczewski 2025-04-12 23:14:39 +02:00
parent 9b073d69f3
commit 60534c4bef
6 changed files with 45 additions and 4 deletions

View file

@ -23,6 +23,7 @@
- fixed sprites rendering black if no shade value is assigned in the level (#2701, regression from 0.8) - fixed sprites rendering black if no shade value is assigned in the level (#2701, regression from 0.8)
- fixed a crash if an image was missing - fixed a crash if an image was missing
- fixed a crash on level load if an animation has no frames (#2746, regression from 0.8) - fixed a crash on level load if an animation has no frames (#2746, regression from 0.8)
- fixed a crash in custom levels with large rooms (#2749)
- removed the need to specify in the game flow levels that have no secrets (secrets will be automatically counted) (#1582) - removed the need to specify in the game flow levels that have no secrets (secrets will be automatically counted) (#1582)
- removed the hard-coded end-level behaviour of the bird guardian for custom levels (#1583) - removed the hard-coded end-level behaviour of the bird guardian for custom levels (#1583)

View file

@ -50,7 +50,6 @@ ENUM_MAP_DEFINE(GAME_BUFFER, GBUF_CREATURE_DATA, "Creature data")
ENUM_MAP_DEFINE(GAME_BUFFER, GBUF_CREATURE_LOT, "Creature pathfinding") ENUM_MAP_DEFINE(GAME_BUFFER, GBUF_CREATURE_LOT, "Creature pathfinding")
ENUM_MAP_DEFINE(GAME_BUFFER, GBUF_SAMPLE_INFOS, "Sample information") ENUM_MAP_DEFINE(GAME_BUFFER, GBUF_SAMPLE_INFOS, "Sample information")
ENUM_MAP_DEFINE(GAME_BUFFER, GBUF_SAMPLES, "Samples") ENUM_MAP_DEFINE(GAME_BUFFER, GBUF_SAMPLES, "Samples")
ENUM_MAP_DEFINE(GAME_BUFFER, GBUF_VERTEX_BUFFER, "Vertex buffer")
ENUM_MAP_DEFINE(UNDERWATER_MUSIC_MODE, UMM_FULL, "full") ENUM_MAP_DEFINE(UNDERWATER_MUSIC_MODE, UMM_FULL, "full")
ENUM_MAP_DEFINE(UNDERWATER_MUSIC_MODE, UMM_QUIET, "quiet") ENUM_MAP_DEFINE(UNDERWATER_MUSIC_MODE, UMM_QUIET, "quiet")

View file

@ -47,7 +47,6 @@ typedef enum {
GBUF_SAMPLE_INFOS, GBUF_SAMPLE_INFOS,
GBUF_SAMPLES, GBUF_SAMPLES,
GBUF_DEMO_BUFFER, GBUF_DEMO_BUFFER,
GBUF_VERTEX_BUFFER,
GBUF_NUM_MALLOC_TYPES, GBUF_NUM_MALLOC_TYPES,
// clang-format on // clang-format on
} GAME_BUFFER; } GAME_BUFFER;

View file

@ -11,11 +11,13 @@
#include "game/viewport.h" #include "game/viewport.h"
#include "global/vars.h" #include "global/vars.h"
#include <libtrx/benchmark.h>
#include <libtrx/config.h> #include <libtrx/config.h>
#include <libtrx/debug.h> #include <libtrx/debug.h>
#include <libtrx/game/math.h> #include <libtrx/game/math.h>
#include <libtrx/game/matrix.h> #include <libtrx/game/matrix.h>
#include <libtrx/log.h> #include <libtrx/log.h>
#include <libtrx/memory.h>
#include <libtrx/utils.h> #include <libtrx/utils.h>
typedef enum { typedef enum {
@ -54,6 +56,7 @@ static NAMED_COLOR m_NamedColors[COLOR_NUMBER_OF] = {
// clang-format on // clang-format on
}; };
static int32_t m_VBufCapacity = 0;
static int32_t m_TickComp = 0; static int32_t m_TickComp = 0;
static int32_t m_LsAdder = 0; static int32_t m_LsAdder = 0;
static int32_t m_LsDivider = 0; static int32_t m_LsDivider = 0;
@ -410,6 +413,44 @@ static void M_CalcSkyboxLight(const OBJECT_MESH *const mesh)
} }
} }
static void M_ReserveVertexBuffer(void)
{
BENCHMARK benchmark = Benchmark_Start();
int32_t max_vertices = 1500;
for (int32_t i = 0; i < O_NUMBER_OF; i++) {
const OBJECT *const obj = Object_Get(i);
if (!obj->loaded) {
continue;
}
for (int32_t j = 0; j < obj->mesh_count; j++) {
const OBJECT_MESH *const mesh = Object_GetMesh(obj->mesh_idx + j);
max_vertices = MAX(max_vertices, mesh->num_vertices);
}
}
for (int32_t i = 0; i < MAX_STATIC_OBJECTS_3D; i++) {
const STATIC_OBJECT_3D *obj = Object_Get3DStatic(i);
if (!obj->loaded) {
continue;
}
const OBJECT_MESH *const mesh = Object_GetMesh(obj->mesh_idx);
max_vertices = MAX(max_vertices, mesh->num_vertices);
}
for (int32_t i = 0; i < Room_GetCount(); i++) {
const ROOM *const room = Room_Get(i);
max_vertices = MAX(max_vertices, room->mesh.num_vertices);
}
Benchmark_End(&benchmark, nullptr);
if (max_vertices >= m_VBufCapacity) {
g_PhdVBuf = Memory_Realloc(g_PhdVBuf, max_vertices * sizeof(PHD_VBUF));
m_VBufCapacity = max_vertices;
}
}
void Output_ApplyLevelSettings(void) void Output_ApplyLevelSettings(void)
{ {
Output_SetWaterColor(Level_GetWaterColor()); Output_SetWaterColor(Level_GetWaterColor());
@ -420,6 +461,7 @@ void Output_ApplyLevelSettings(void)
void Output_ObserveLevelLoad(void) void Output_ObserveLevelLoad(void)
{ {
M_ReserveVertexBuffer();
Output_ApplyLevelSettings(); Output_ApplyLevelSettings();
for (int32_t i = 0; i < COLOR_NUMBER_OF; i++) { for (int32_t i = 0; i < COLOR_NUMBER_OF; i++) {
m_NamedColors[i].palette_index = m_NamedColors[i].palette_index =

View file

@ -44,7 +44,7 @@ float g_FltPersp;
int16_t *g_Info3DPtr = nullptr; int16_t *g_Info3DPtr = nullptr;
int32_t g_PhdWinWidth; int32_t g_PhdWinWidth;
int32_t g_PhdViewDistance; int32_t g_PhdViewDistance;
PHD_VBUF g_PhdVBuf[1500]; PHD_VBUF *g_PhdVBuf = nullptr;
float g_FltWinRight; float g_FltWinRight;
int32_t g_PhdWinRight; int32_t g_PhdWinRight;
int32_t g_SurfaceCount; int32_t g_SurfaceCount;

View file

@ -45,7 +45,7 @@ extern float g_FltPersp;
extern int16_t *g_Info3DPtr; extern int16_t *g_Info3DPtr;
extern int32_t g_PhdWinWidth; extern int32_t g_PhdWinWidth;
extern int32_t g_PhdViewDistance; extern int32_t g_PhdViewDistance;
extern PHD_VBUF g_PhdVBuf[]; extern PHD_VBUF *g_PhdVBuf;
extern float g_FltWinRight; extern float g_FltWinRight;
extern int32_t g_PhdWinRight; extern int32_t g_PhdWinRight;
extern int32_t g_SurfaceCount; extern int32_t g_SurfaceCount;