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 90b7b42
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 18 deletions.
75 changes: 61 additions & 14 deletions src/libtrx/game/packer.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "game/packer.h"

#include "debug.h"
#include "game/output.h"
#include "log.h"
#include "memory.h"
Expand Down Expand Up @@ -65,6 +66,7 @@ static bool M_PackContainerAt(
const TEX_CONTAINER *container, TEX_PAGE *page, int32_t x_pos,
int32_t y_pos);
static bool M_PackContainer(const TEX_CONTAINER *container);
static uint8_t M_GetPaletteMatch(const RGBA_8888 *colour);

static PACKER_DATA *m_Data = NULL;
static int32_t m_StartPage = 0;
Expand Down Expand Up @@ -239,24 +241,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 *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 @@ -280,9 +297,12 @@ static bool M_PackContainerAt(
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];
&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];
uint8_t *const level_page_24 = m_Data->level.pages_24 == NULL
? NULL
: &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 +311,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[old_pixel];
if (level_page_24 != NULL) {
level_page_24[new_pixel] =
M_GetPaletteMatch(&source_page[old_pixel]);
}
}
}

Expand All @@ -309,6 +333,29 @@ static bool M_PackContainerAt(
return true;
}

static uint8_t M_GetPaletteMatch(const RGBA_8888 *const colour)
{
if (colour->a == 0) {
return 0;
}

ASSERT(m_Data->game_palette != NULL);
int32_t best_idx = 0;
int32_t best_diff = INT32_MAX;
for (int32_t i = 1; i < 256; i++) {
const int32_t dr = colour->r - m_Data->game_palette[i].r;
const int32_t dg = colour->g - m_Data->game_palette[i].g;
const int32_t db = colour->b - m_Data->game_palette[i].b;
const int32_t diff = SQUARE(dr) + SQUARE(dg) + SQUARE(db);
if (diff < best_diff) {
best_diff = diff;
best_idx = i;
}
}

return (uint8_t)best_idx;
}

static void M_MoveObject(
const int32_t index, const RECTANGLE old_bounds, const TEX_POS new_pos)
{
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,8 +7,10 @@
typedef struct {
struct {
int32_t page_count;
RGBA_8888 *pages;
RGBA_8888 *pages_32;
uint8_t *pages_24;
} source, level;
RGB_888 *game_palette;
int32_t object_count;
int32_t sprite_count;
} PACKER_DATA;
Expand Down
8 changes: 5 additions & 3 deletions src/tr1/game/inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1673,16 +1673,18 @@ 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,
.source.page_count = source_page_count,
.source.pages = source_pages,
.source.pages_32 = source_pages,
.game_palette = 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 90b7b42

Please sign in to comment.