diff --git a/src/libtrx/game/packer.c b/src/libtrx/game/packer.c index 5eb35cacc..f7b91cef4 100644 --- a/src/libtrx/game/packer.c +++ b/src/libtrx/game/packer.c @@ -1,5 +1,6 @@ #include "game/packer.h" +#include "debug.h" #include "game/output.h" #include "log.h" #include "memory.h" @@ -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; @@ -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( @@ -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++) { @@ -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]); + } } } @@ -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) { diff --git a/src/libtrx/include/libtrx/game/packer.h b/src/libtrx/include/libtrx/game/packer.h index 23cd24e90..f016697d1 100644 --- a/src/libtrx/include/libtrx/game/packer.h +++ b/src/libtrx/include/libtrx/game/packer.h @@ -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; diff --git a/src/tr1/game/inject.c b/src/tr1/game/inject.c index 97cce1612..d64bbed2c 100644 --- a/src/tr1/game/inject.c +++ b/src/tr1/game/inject.c @@ -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);