Skip to content

Commit

Permalink
packer: prepare for 8-bit packing
Browse files Browse the repository at this point in the history
This allows the packer to accept an 8-bit texture page array, on the
grounds that texture layout is identical to 32-bit. This is in
preparation for TR2.
  • Loading branch information
lahm86 committed Jan 26, 2025
1 parent 27cb83a commit 3f78da9
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 19 deletions.
94 changes: 79 additions & 15 deletions src/libtrx/game/packer.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "game/packer.h"

#include "benchmark.h"
#include "debug.h"
#include "game/output.h"
#include "log.h"
#include "memory.h"
Expand Down Expand Up @@ -47,6 +49,7 @@ typedef struct {
uint8_t data[TEXTURE_PAGE_SIZE];
} TEX_PAGE;

static void M_PreparePaletteLUT(void);
static void M_AllocateNewPage(void);
static void M_FillVirtualData(TEX_PAGE *page, RECTANGLE bounds);
static void M_Cleanup(void);
Expand All @@ -67,13 +70,43 @@ static bool M_PackContainerAt(
static bool M_PackContainer(const TEX_CONTAINER *container);

static PACKER_DATA *m_Data = NULL;
static uint8_t m_PaletteLUT[256];
static int32_t m_StartPage = 0;
static int32_t m_EndPage = 0;
static int32_t m_UsedPageCount = 0;
static TEX_PAGE *m_VirtualPages = NULL;
static int32_t m_QueueSize = 0;
static TEX_CONTAINER *m_Queue = NULL;

static void M_PreparePaletteLUT(void)
{
if (m_Data->level.pages_24 == NULL) {
return;
}

ASSERT(m_Data->source.palette_24 != NULL);
ASSERT(m_Data->level.palette_24 != NULL);

m_PaletteLUT[0] = 0;
for (int32_t i = 1; i < 256; i++) {
const RGB_888 colour = m_Data->source.palette_24[i];
int32_t best_idx = 0;
int32_t best_diff = INT32_MAX;
for (int32_t j = 1; j < 256; j++) {
const int32_t dr = colour.r - m_Data->level.palette_24[j].r;
const int32_t dg = colour.g - m_Data->level.palette_24[j].g;
const int32_t db = colour.b - m_Data->level.palette_24[j].b;
const int32_t diff = SQUARE(dr) + SQUARE(dg) + SQUARE(db);
if (diff < best_diff) {
best_diff = diff;
best_idx = j;
}
}

m_PaletteLUT[i] = (uint8_t)best_idx;
}
}

static void M_PrepareObject(const int32_t object_index)
{
const OBJECT_TEXTURE *const object_texture =
Expand Down Expand Up @@ -239,24 +272,39 @@ static bool M_PackContainer(const TEX_CONTAINER *const container)

static void M_AllocateNewPage(void)
{
m_VirtualPages = Memory_Realloc(
m_VirtualPages, sizeof(TEX_PAGE) * (m_UsedPageCount + 1));
TEX_PAGE *const page = &m_VirtualPages[m_UsedPageCount];
page->index = m_StartPage + m_UsedPageCount;
const int32_t used_count = m_UsedPageCount;
m_UsedPageCount++;

m_VirtualPages =
Memory_Realloc(m_VirtualPages, sizeof(TEX_PAGE) * (used_count + 1));
TEX_PAGE *const page = &m_VirtualPages[used_count];
page->index = m_StartPage + used_count;
page->free_space = TEXTURE_PAGE_SIZE;
memset(page->data, 0, TEXTURE_PAGE_SIZE * sizeof(uint8_t));

if (m_UsedPageCount > 0) {
const int32_t new_count = m_Data->level.page_count + m_UsedPageCount;
m_Data->level.pages = Memory_Realloc(
m_Data->level.pages,
if (used_count == 0) {
return;
}

const int32_t new_count = m_Data->level.page_count + used_count;

{
m_Data->level.pages_32 = Memory_Realloc(
m_Data->level.pages_32,
TEXTURE_PAGE_SIZE * new_count * sizeof(RGBA_8888));
RGBA_8888 *const level_page =
&m_Data->level.pages[(new_count - 1) * TEXTURE_PAGE_SIZE];
&m_Data->level.pages_32[(new_count - 1) * TEXTURE_PAGE_SIZE];
memset(level_page, 0, TEXTURE_PAGE_SIZE * sizeof(RGBA_8888));
}

m_UsedPageCount++;
if (m_Data->level.pages_24 != NULL) {
m_Data->level.pages_24 = Memory_Realloc(
m_Data->level.pages_24,
TEXTURE_PAGE_SIZE * new_count * sizeof(uint8_t));
uint8_t *const level_page =
&m_Data->level.pages_24[(new_count - 1) * TEXTURE_PAGE_SIZE];
memset(level_page, 0, TEXTURE_PAGE_SIZE * sizeof(uint8_t));
}
}

static bool M_PackContainerAt(
Expand All @@ -279,10 +327,19 @@ static bool M_PackContainerAt(
// data to avoid anything else taking this position.
const int32_t source_page_index =
container->tex_infos->page - m_Data->level.page_count;
const RGBA_8888 *const source_page =
&m_Data->source.pages[source_page_index * TEXTURE_PAGE_SIZE];
RGBA_8888 *const level_page =
&m_Data->level.pages[page->index * TEXTURE_PAGE_SIZE];
const RGBA_8888 *const source_page_32 =
&m_Data->source.pages_32[source_page_index * TEXTURE_PAGE_SIZE];
RGBA_8888 *const level_page_32 =
&m_Data->level.pages_32[page->index * TEXTURE_PAGE_SIZE];

const uint8_t *source_page_24 = NULL;
uint8_t *level_page_24 = NULL;
if (m_Data->level.pages_24 != NULL) {
source_page_24 =
&m_Data->source.pages_24[source_page_index * TEXTURE_PAGE_SIZE];
level_page_24 =
&m_Data->level.pages_24[page->index * TEXTURE_PAGE_SIZE];
}

int32_t old_pixel, new_pixel;
for (int32_t y = 0; y < container->bounds.h; y++) {
Expand All @@ -291,7 +348,11 @@ static bool M_PackContainerAt(
+ container->bounds.x + x;
new_pixel = (y_pos + y) * TEXTURE_PAGE_WIDTH + x_pos + x;
page->data[new_pixel] = 1;
level_page[new_pixel] = source_page[old_pixel];
level_page_32[new_pixel] = source_page_32[old_pixel];
if (level_page_24 != NULL) {
level_page_24[new_pixel] =
m_PaletteLUT[source_page_24[old_pixel]];
}
}
}

Expand Down Expand Up @@ -370,7 +431,9 @@ static void M_Cleanup(void)

bool Packer_Pack(PACKER_DATA *const data)
{
BENCHMARK *const benchmark = Benchmark_Start();
m_Data = data;
M_PreparePaletteLUT();

m_StartPage = m_Data->level.page_count - 1;
m_EndPage = MAX_TEXTURE_PAGES - m_StartPage;
Expand All @@ -397,6 +460,7 @@ bool Packer_Pack(PACKER_DATA *const data)
}

M_Cleanup();
Benchmark_End(benchmark, NULL);
return result;
}

Expand Down
4 changes: 3 additions & 1 deletion src/libtrx/include/libtrx/game/packer.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
typedef struct {
struct {
int32_t page_count;
RGBA_8888 *pages;
RGBA_8888 *pages_32;
uint8_t *pages_24;
RGB_888 *palette_24;
} source, level;
int32_t object_count;
int32_t sprite_count;
Expand Down
10 changes: 7 additions & 3 deletions src/tr1/game/inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1673,16 +1673,20 @@ void Inject_AllInjections(LEVEL_INFO *level_info)
if (source_page_count != 0) {
PACKER_DATA data = {
.level.page_count = level_info->texture_page_count,
.level.pages = level_info->texture_rgb_page_ptrs,
.level.pages_32 = level_info->texture_rgb_page_ptrs,
.level.pages_24 = NULL,
.level.palette_24 = NULL,
.source.page_count = source_page_count,
.source.pages = source_pages,
.source.pages_32 = source_pages,
.source.pages_24 = NULL,
.source.palette_24 = NULL,
.object_count = level_info->texture_count,
.sprite_count = level_info->sprite_info_count,
};

if (Packer_Pack(&data)) {
level_info->texture_page_count += Packer_GetAddedPageCount();
level_info->texture_rgb_page_ptrs = data.level.pages;
level_info->texture_rgb_page_ptrs = data.level.pages_32;
}

Memory_FreePointer(&source_pages);
Expand Down

0 comments on commit 3f78da9

Please sign in to comment.