From 3f78da976eef97faa243c3e8140c4f58a2beaac6 Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Sun, 26 Jan 2025 15:37:58 +0000 Subject: [PATCH] packer: prepare for 8-bit packing 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. --- src/libtrx/game/packer.c | 94 +++++++++++++++++++++---- src/libtrx/include/libtrx/game/packer.h | 4 +- src/tr1/game/inject.c | 10 ++- 3 files changed, 89 insertions(+), 19 deletions(-) diff --git a/src/libtrx/game/packer.c b/src/libtrx/game/packer.c index 5eb35cacc..a179a6b3e 100644 --- a/src/libtrx/game/packer.c +++ b/src/libtrx/game/packer.c @@ -1,5 +1,7 @@ #include "game/packer.h" +#include "benchmark.h" +#include "debug.h" #include "game/output.h" #include "log.h" #include "memory.h" @@ -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); @@ -67,6 +70,7 @@ 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; @@ -74,6 +78,35 @@ 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 = @@ -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( @@ -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++) { @@ -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]]; + } } } @@ -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; @@ -397,6 +460,7 @@ bool Packer_Pack(PACKER_DATA *const data) } M_Cleanup(); + Benchmark_End(benchmark, NULL); return result; } diff --git a/src/libtrx/include/libtrx/game/packer.h b/src/libtrx/include/libtrx/game/packer.h index 23cd24e90..df3fe1824 100644 --- a/src/libtrx/include/libtrx/game/packer.h +++ b/src/libtrx/include/libtrx/game/packer.h @@ -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; diff --git a/src/tr1/game/inject.c b/src/tr1/game/inject.c index 97cce1612..8564e1b2d 100644 --- a/src/tr1/game/inject.c +++ b/src/tr1/game/inject.c @@ -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);