Skip to content

Commit

Permalink
level: handle texture and palette reading in TRX
Browse files Browse the repository at this point in the history
This makes the palette and texture page readers for both games common
in TRX.
  • Loading branch information
lahm86 committed Jan 31, 2025
1 parent f750ff9 commit 8449b1c
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 131 deletions.
105 changes: 105 additions & 0 deletions src/libtrx/game/level/common.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "game/level/common.h"

#include "benchmark.h"
#include "debug.h"
#include "game/anims.h"
#include "game/const.h"
Expand All @@ -16,12 +17,35 @@

static int16_t *m_AnimCommands = nullptr;

static RGBA_8888 M_ARGB1555To8888(uint16_t argb1555);
static void M_ReadVertex(XYZ_16 *vertex, VFILE *file);
static void M_ReadFace4(FACE4 *face, VFILE *file);
static void M_ReadFace3(FACE3 *face, VFILE *file);
static void M_ReadObjectMesh(OBJECT_MESH *mesh, VFILE *file);
static void M_ReadBounds16(BOUNDS_16 *bounds, VFILE *file);

static RGBA_8888 M_ARGB1555To8888(const uint16_t argb1555)
{
// Extract 5-bit values for each ARGB component
uint8_t a1 = (argb1555 >> 15) & 0x01;
uint8_t r5 = (argb1555 >> 10) & 0x1F;
uint8_t g5 = (argb1555 >> 5) & 0x1F;
uint8_t b5 = argb1555 & 0x1F;

// Expand 5-bit color components to 8-bit
uint8_t a8 = a1 * 255; // 1-bit alpha (either 0 or 255)
uint8_t r8 = (r5 << 3) | (r5 >> 2);
uint8_t g8 = (g5 << 3) | (g5 >> 2);
uint8_t b8 = (b5 << 3) | (b5 >> 2);

return (RGBA_8888) {
.r = r8,
.g = g8,
.b = b8,
.a = a8,
};
}

static void M_ReadVertex(XYZ_16 *const vertex, VFILE *const file)
{
vertex->x = VFile_ReadS16(file);
Expand Down Expand Up @@ -128,6 +152,87 @@ static void M_ReadBounds16(BOUNDS_16 *const bounds, VFILE *const file)
bounds->max.z = VFile_ReadS16(file);
}

void Level_ReadPalette(LEVEL_INFO *const info, VFILE *const file)
{
BENCHMARK *const benchmark = Benchmark_Start();

const int32_t palette_size = 256;
info->palette.size = palette_size;

info->palette.data_24 = Memory_Alloc(sizeof(RGB_888) * palette_size);
VFile_Read(file, info->palette.data_24, sizeof(RGB_888) * palette_size);
info->palette.data_24[0].r = 0;
info->palette.data_24[0].g = 0;
info->palette.data_24[0].b = 0;
for (int32_t i = 1; i < palette_size; i++) {
RGB_888 *const col = &info->palette.data_24[i];
col->r = (col->r << 2) | (col->r >> 4);
col->g = (col->g << 2) | (col->g >> 4);
col->b = (col->b << 2) | (col->b >> 4);
}

#if TR_VERSION == 1
info->palette.data_32 = nullptr;
#else
RGBA_8888 palette_16[palette_size];
info->palette.data_32 = Memory_Alloc(sizeof(RGB_888) * palette_size);
VFile_Read(file, palette_16, sizeof(RGBA_8888) * palette_size);
for (int32_t i = 0; i < palette_size; i++) {
info->palette.data_32[i].r = palette_16[i].r;
info->palette.data_32[i].g = palette_16[i].g;
info->palette.data_32[i].b = palette_16[i].b;
}
#endif

Benchmark_End(benchmark, nullptr);
}

// TODO: replace extra_pages with value from injection interface
void Level_ReadTexturePages(
LEVEL_INFO *const info, const int32_t extra_pages, VFILE *const file)
{
BENCHMARK *const benchmark = Benchmark_Start();

const int32_t num_pages = VFile_ReadS32(file);
info->textures.page_count = num_pages;
LOG_INFO("texture pages: %d", num_pages);

const int32_t texture_size_8_bit =
num_pages * TEXTURE_PAGE_SIZE * sizeof(uint8_t);
const int32_t texture_size_32_bit =
(num_pages + extra_pages) * TEXTURE_PAGE_SIZE * sizeof(RGBA_8888);

info->textures.pages_24 = Memory_Alloc(texture_size_8_bit);
VFile_Read(file, info->textures.pages_24, texture_size_8_bit);

info->textures.pages_32 = Memory_Alloc(texture_size_32_bit);
RGBA_8888 *output = info->textures.pages_32;

#if TR_VERSION == 1
const uint8_t *input = info->textures.pages_24;
for (int32_t i = 0; i < texture_size_8_bit; i++) {
const uint8_t index = *input++;
const RGB_888 pix = info->palette.data_24[index];
output->r = pix.r;
output->g = pix.g;
output->b = pix.b;
output->a = index == 0 ? 0 : 0xFF;
output++;
}
#else
const int32_t texture_size_16_bit =
num_pages * TEXTURE_PAGE_SIZE * sizeof(uint16_t);
uint16_t *input = Memory_Alloc(texture_size_16_bit);
VFile_Read(file, input, texture_size_16_bit);
for (int32_t i = 0; i < num_pages * TEXTURE_PAGE_SIZE; i++) {
*output++ = M_ARGB1555To8888(*input++);
}
Memory_FreePointer(&input);
#endif

Benchmark_End(benchmark, NULL);
}

void Level_ReadRoomMesh(const int32_t room_num, VFILE *const file)
{
ROOM *const room = Room_Get(room_num);
Expand Down
2 changes: 2 additions & 0 deletions src/libtrx/include/libtrx/game/level/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#define ANIM_BONE_SIZE 4

void Level_ReadPalette(LEVEL_INFO *info, VFILE *file);
void Level_ReadTexturePages(LEVEL_INFO *info, int32_t extra_pages, VFILE *file);
void Level_ReadRoomMesh(int32_t room_num, VFILE *file);
void Level_ReadFloorData(VFILE *file);
void Level_ReadObjectMeshes(
Expand Down
46 changes: 3 additions & 43 deletions src/tr1/game/level.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,33 +261,8 @@ static void M_LoadFromFile(const GF_LEVEL *const level)

static void M_LoadTexturePages(VFILE *file)
{
BENCHMARK *const benchmark = Benchmark_Start();
const int32_t num_pages = VFile_ReadS32(file);
m_LevelInfo.textures.page_count = num_pages;
LOG_INFO("%d texture pages", num_pages);

const int32_t texture_size_8_bit =
num_pages * TEXTURE_PAGE_SIZE * sizeof(uint8_t);
m_LevelInfo.textures.pages_24 = Memory_Alloc(texture_size_8_bit);
VFile_Read(file, m_LevelInfo.textures.pages_24, texture_size_8_bit);

const int32_t texture_size_32_bit =
(num_pages + m_InjectionInfo->texture_page_count) * TEXTURE_PAGE_SIZE
* sizeof(RGBA_8888);
m_LevelInfo.textures.pages_32 = Memory_Alloc(texture_size_32_bit);
RGBA_8888 *output = m_LevelInfo.textures.pages_32;
const uint8_t *input = m_LevelInfo.textures.pages_24;
for (int32_t i = 0; i < texture_size_8_bit; i++) {
const uint8_t index = *input++;
const RGB_888 pix = m_LevelInfo.palette.data_24[index];
output->r = pix.r;
output->g = pix.g;
output->b = pix.b;
output->a = index == 0 ? 0 : 0xFF;
output++;
}

Benchmark_End(benchmark, nullptr);
Level_ReadTexturePages(
&m_LevelInfo, m_InjectionInfo->texture_page_count, file);
}

static void M_LoadRooms(VFILE *file)
Expand Down Expand Up @@ -705,22 +680,7 @@ static void M_LoadLightTable(VFILE *file)

static void M_LoadPalette(VFILE *file)
{
BENCHMARK *const benchmark = Benchmark_Start();
LOG_INFO("");
m_LevelInfo.palette.size = 256;
m_LevelInfo.palette.data_24 =
Memory_Alloc(sizeof(RGB_888) * m_LevelInfo.palette.size);
for (int32_t i = 0; i < 256; i++) {
m_LevelInfo.palette.data_24[i].r = VFile_ReadU8(file) * 4;
m_LevelInfo.palette.data_24[i].g = VFile_ReadU8(file) * 4;
m_LevelInfo.palette.data_24[i].b = VFile_ReadU8(file) * 4;
}
m_LevelInfo.palette.data_24[0].r = 0;
m_LevelInfo.palette.data_24[0].g = 0;
m_LevelInfo.palette.data_24[0].b = 0;

m_LevelInfo.palette.data_32 = nullptr;
Benchmark_End(benchmark, nullptr);
Level_ReadPalette(&m_LevelInfo, file);
}

static void M_LoadCinematic(VFILE *file)
Expand Down
59 changes: 2 additions & 57 deletions src/tr2/game/level.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include "game/output.h"
#include "game/overlay.h"
#include "game/render/common.h"
#include "game/render/util.h"
#include "game/room.h"
#include "game/shell.h"
#include "game/sound.h"
Expand Down Expand Up @@ -60,34 +59,7 @@ static void M_CompleteSetup(void);

static void M_LoadTexturePages(VFILE *const file)
{
BENCHMARK *const benchmark = Benchmark_Start();

const int32_t num_pages = VFile_ReadS32(file);
m_LevelInfo.textures.page_count = num_pages;
LOG_INFO("texture pages: %d", num_pages);

const int32_t texture_size_8_bit =
num_pages * TEXTURE_PAGE_SIZE * sizeof(uint8_t);
const int32_t texture_size_16_bit =
num_pages * TEXTURE_PAGE_SIZE * sizeof(uint16_t);
const int32_t texture_size_32_bit =
num_pages * TEXTURE_PAGE_SIZE * sizeof(RGBA_8888);

m_LevelInfo.textures.pages_24 = Memory_Alloc(texture_size_8_bit);
VFile_Read(file, m_LevelInfo.textures.pages_24, texture_size_8_bit);

m_LevelInfo.textures.pages_32 = Memory_Alloc(texture_size_32_bit);

uint16_t *input = Memory_Alloc(texture_size_16_bit);
VFile_Read(file, input, texture_size_16_bit);
RGBA_8888 *output = m_LevelInfo.textures.pages_32;
for (int32_t i = 0; i < num_pages * TEXTURE_PAGE_SIZE; i++) {
*output++ = Render_ARGB1555To8888(*input++);
}

Memory_FreePointer(&input);

Benchmark_End(benchmark, NULL);
Level_ReadTexturePages(&m_LevelInfo, 0, file);
}

static void M_LoadRooms(VFILE *const file)
Expand Down Expand Up @@ -395,34 +367,7 @@ static void M_LoadDepthQ(VFILE *const file)

static void M_LoadPalettes(VFILE *const file)
{
BENCHMARK *const benchmark = Benchmark_Start();

const int32_t palette_size = 256;
m_LevelInfo.palette.size = palette_size;
m_LevelInfo.palette.data_24 = Memory_Alloc(sizeof(RGB_888) * palette_size);
m_LevelInfo.palette.data_32 = Memory_Alloc(sizeof(RGB_888) * palette_size);

VFile_Read(
file, m_LevelInfo.palette.data_24, sizeof(RGB_888) * palette_size);
m_LevelInfo.palette.data_24[0].r = 0;
m_LevelInfo.palette.data_24[0].g = 0;
m_LevelInfo.palette.data_24[0].b = 0;
for (int32_t i = 1; i < palette_size; i++) {
RGB_888 *const col = &m_LevelInfo.palette.data_24[i];
col->r = (col->r << 2) | (col->r >> 4);
col->g = (col->g << 2) | (col->g >> 4);
col->b = (col->b << 2) | (col->b >> 4);
}

RGBA_8888 palette_16[palette_size];
VFile_Read(file, palette_16, sizeof(RGBA_8888) * palette_size);
for (int32_t i = 0; i < palette_size; i++) {
m_LevelInfo.palette.data_32[i].r = palette_16[i].r;
m_LevelInfo.palette.data_32[i].g = palette_16[i].g;
m_LevelInfo.palette.data_32[i].b = palette_16[i].b;
}

Benchmark_End(benchmark, nullptr);
Level_ReadPalette(&m_LevelInfo, file);
}

static void M_LoadCameras(VFILE *const file)
Expand Down
1 change: 0 additions & 1 deletion src/tr2/game/render/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include "game/render/hwr.h"
#include "game/render/priv.h"
#include "game/render/swr.h"
#include "game/render/util.h"
#include "game/shell.h"
#include "global/vars.h"

Expand Down
1 change: 0 additions & 1 deletion src/tr2/game/render/hwr.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include "decomp/decomp.h"
#include "game/output.h"
#include "game/render/priv.h"
#include "game/render/util.h"
#include "game/shell.h"
#include "global/vars.h"

Expand Down
23 changes: 0 additions & 23 deletions src/tr2/game/render/util.c

This file was deleted.

5 changes: 0 additions & 5 deletions src/tr2/game/render/util.h

This file was deleted.

1 change: 0 additions & 1 deletion src/tr2/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,6 @@ sources = [
'game/render/hwr.c',
'game/render/priv.c',
'game/render/swr.c',
'game/render/util.c',
'game/requester.c',
'game/room.c',
'game/room_draw.c',
Expand Down

0 comments on commit 8449b1c

Please sign in to comment.