Skip to content

Commit

Permalink
inject: allow mixing game palettes
Browse files Browse the repository at this point in the history
  • Loading branch information
rr- committed Sep 14, 2024
1 parent 8d9b823 commit c769439
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 48 deletions.
41 changes: 32 additions & 9 deletions src/game/inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ static void Inject_AlignTextureReferences(
OBJECT_INFO *object, uint8_t *palette_map, int32_t page_base);

static void Inject_LoadTexturePages(
INJECTION *injection, uint8_t *palette_map, uint8_t *page_ptr);
INJECTION *injection, uint8_t *palette_map, RGBA_8888 *page_ptr);
static void Inject_TextureData(
INJECTION *injection, LEVEL_INFO *level_info, int32_t page_base);
static void Inject_MeshData(INJECTION *injection, LEVEL_INFO *level_info);
Expand Down Expand Up @@ -383,8 +383,8 @@ void Inject_AllInjections(LEVEL_INFO *level_info)
BENCHMARK *const benchmark = Benchmark_Start();

uint8_t palette_map[256];
uint8_t *source_pages =
Memory_Alloc(m_Aggregate->texture_page_count * PAGE_SIZE);
RGBA_8888 *source_pages = Memory_Alloc(
m_Aggregate->texture_page_count * PAGE_SIZE * sizeof(RGBA_8888));
int32_t source_page_count = 0;
int32_t tpage_base = level_info->texture_page_count;

Expand Down Expand Up @@ -450,7 +450,7 @@ void Inject_AllInjections(LEVEL_INFO *level_info)
}

static void Inject_LoadTexturePages(
INJECTION *injection, uint8_t *palette_map, uint8_t *page_ptr)
INJECTION *injection, uint8_t *palette_map, RGBA_8888 *page_ptr)
{
BENCHMARK *const benchmark = Benchmark_Start();

Expand All @@ -475,10 +475,23 @@ static void Inject_LoadTexturePages(
// Read in each page for this injection and realign the pixels
// to the level's palette.
const size_t pixel_count = PAGE_SIZE * inj_info->texture_page_count;
VFile_Read(fp, page_ptr, pixel_count);
for (size_t i = 0; i < pixel_count; i++, page_ptr++) {
*page_ptr = palette_map[*page_ptr];
uint8_t *indices = Memory_Alloc(pixel_count);
VFile_Read(fp, indices, pixel_count);
uint8_t *input = indices;
RGBA_8888 *output = page_ptr;
for (size_t i = 0; i < pixel_count; i++) {
const uint8_t index = *input++;
if (index == 0) {
output->a = 0;
} else {
output->r = source_palette[index].r;
output->g = source_palette[index].g;
output->b = source_palette[index].b;
output->a = 255;
}
output++;
}
Memory_FreePointer(&indices);

Benchmark_End(benchmark, NULL);
}
Expand Down Expand Up @@ -1133,13 +1146,23 @@ static void Inject_TextureOverwrites(
VFile_Read(fp, source_img, source_width * source_height);

// Copy the source image pixels directly into the target page.
uint8_t *page = level_info->texture_page_ptrs + target_page * PAGE_SIZE;
RGBA_8888 *page =
level_info->texture_page_ptrs + target_page * PAGE_SIZE;
for (int32_t y = 0; y < source_height; y++) {
for (int32_t x = 0; x < source_width; x++) {
const int32_t pal_idx = source_img[y * source_width + x];
const int32_t target_pixel =
(y + target_y) * PAGE_WIDTH + x + target_x;
*(page + target_pixel) = palette_map[pal_idx];
if (pal_idx == 0) {
(*(page + target_pixel)).a = 0;
} else {
const RGB_888 pix =
Output_GetPaletteColor(palette_map[pal_idx]);
(*(page + target_pixel)).r = pix.r;
(*(page + target_pixel)).g = pix.g;
(*(page + target_pixel)).b = pix.b;
(*(page + target_pixel)).a = 255;
}
}
}

Expand Down
36 changes: 28 additions & 8 deletions src/game/level.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,10 @@ static void Level_LoadTexturePages(VFILE *file)
BENCHMARK *const benchmark = Benchmark_Start();
m_LevelInfo.texture_page_count = VFile_ReadS32(file);
LOG_INFO("%d texture pages", m_LevelInfo.texture_page_count);
m_LevelInfo.texture_page_ptrs =
m_LevelInfo.texture_old_page_ptrs =
Memory_Alloc(m_LevelInfo.texture_page_count * PAGE_SIZE);
VFile_Read(
file, m_LevelInfo.texture_page_ptrs,
file, m_LevelInfo.texture_old_page_ptrs,
PAGE_SIZE * m_LevelInfo.texture_page_count);
Benchmark_End(benchmark, NULL);
}
Expand Down Expand Up @@ -897,6 +897,30 @@ static void Level_CompleteSetup(int32_t level_num)
Room_ParseFloorData(m_LevelInfo.floor_data);
Memory_FreePointer(&m_LevelInfo.floor_data);

// Expand texture data to RGB true color
m_LevelInfo.texture_page_ptrs = Memory_Alloc(
m_LevelInfo.texture_page_count * PAGE_SIZE * sizeof(RGBA_8888));
RGBA_8888 *output = m_LevelInfo.texture_page_ptrs;
const uint8_t *input = m_LevelInfo.texture_old_page_ptrs;
for (int i = 0; i < m_LevelInfo.texture_page_count; i++) {
for (int32_t j = 0; j < PAGE_SIZE; j++) {
const uint8_t index = *input++;
if (index == 0) {
output->r = 0;
output->g = 0;
output->b = 0;
output->a = 0;
} else {
RGB_888 pix = Output_GetPaletteColor(index);
output->r = pix.r;
output->g = pix.g;
output->b = pix.b;
output->a = 255;
}
output++;
}
}

Inject_AllInjections(&m_LevelInfo);

Level_MarkWaterEdgeVertices();
Expand All @@ -921,12 +945,8 @@ static void Level_CompleteSetup(int32_t level_num)
Output_ReserveVertexBuffer(max_vertices);

// Move the prepared texture pages into g_TexturePagePtrs.
uint8_t *base = GameBuf_Alloc(
m_LevelInfo.texture_page_count * PAGE_SIZE, GBUF_TEXTURE_PAGES);
for (int i = 0; i < m_LevelInfo.texture_page_count; i++) {
g_TexturePagePtrs[i] = base;
memcpy(base, m_LevelInfo.texture_page_ptrs + i * PAGE_SIZE, PAGE_SIZE);
base += PAGE_SIZE;
g_TexturePagePtrs[i] = &m_LevelInfo.texture_page_ptrs[i * PAGE_SIZE];
}
Output_DownloadTextures(m_LevelInfo.texture_page_count);

Expand Down Expand Up @@ -1021,7 +1041,7 @@ void Level_Load(int level_num)
BENCHMARK *const benchmark = Benchmark_Start();

// clean previous level data
Memory_FreePointer(&m_LevelInfo.texture_page_ptrs);
Memory_FreePointer(&m_LevelInfo.texture_old_page_ptrs);
Memory_FreePointer(&m_LevelInfo.anim_frame_offsets);
Memory_FreePointer(&m_LevelInfo.sample_offsets);
Memory_FreePointer(&m_InjectionInfo);
Expand Down
38 changes: 23 additions & 15 deletions src/game/packer.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <libtrx/memory.h>
#include <libtrx/utils.h>

#include <string.h>
#include <stddef.h>

typedef enum RECTANGLE_COMPARISON {
Expand Down Expand Up @@ -42,7 +43,7 @@ typedef struct TEX_CONTAINER {
typedef struct TEX_PAGE {
int32_t index;
int32_t free_space;
uint8_t data[PAGE_SIZE];
RGBA_8888 data[PAGE_SIZE];
} TEX_PAGE;

static void Packer_AllocateNewPage(void);
Expand Down Expand Up @@ -153,7 +154,10 @@ static void Packer_FillVirtualData(TEX_PAGE *page, RECTANGLE *bounds)
int x_end = bounds->x + bounds->w;
for (int y = bounds->y; y < y_end; y++) {
for (int x = bounds->x; x < x_end; x++) {
page->data[y * PAGE_WIDTH + x] = 1;
page->data[y * PAGE_WIDTH + x].r = 1;
page->data[y * PAGE_WIDTH + x].g = 1;
page->data[y * PAGE_WIDTH + x].b = 1;
page->data[y * PAGE_WIDTH + x].a = 255;
}
}

Expand Down Expand Up @@ -281,18 +285,15 @@ static void Packer_AllocateNewPage(void)
TEX_PAGE *page = &m_VirtualPages[m_UsedPageCount];
page->index = m_StartPage + m_UsedPageCount;
page->free_space = PAGE_SIZE;
for (int i = 0; i < PAGE_SIZE; i++) {
page->data[i] = 0;
}
memset(page->data, 0, PAGE_SIZE * sizeof(RGBA_8888));

if (m_UsedPageCount > 0) {
int new_count = m_Data->level_page_count + m_UsedPageCount;
m_Data->level_pages =
Memory_Realloc(m_Data->level_pages, PAGE_SIZE * new_count);
uint8_t *level_page = m_Data->level_pages + (new_count - 1) * PAGE_SIZE;
for (int i = 0; i < PAGE_SIZE; i++) {
*(level_page + i) = 0;
}
m_Data->level_pages = Memory_Realloc(
m_Data->level_pages, PAGE_SIZE * new_count * sizeof(RGBA_8888));
RGBA_8888 *level_page =
m_Data->level_pages + (new_count - 1) * PAGE_SIZE;
memset(level_page, 0, PAGE_SIZE * sizeof(RGBA_8888));
}

m_UsedPageCount++;
Expand All @@ -306,7 +307,10 @@ static bool Packer_PackContainerAt(

for (int y = y_pos; y < y_end; y++) {
for (int x = x_pos; x < x_end; x++) {
if (page->data[y * PAGE_WIDTH + x]) {
if (page->data[y * PAGE_WIDTH + x].r
|| page->data[y * PAGE_WIDTH + x].g
|| page->data[y * PAGE_WIDTH + x].b
|| page->data[y * PAGE_WIDTH + x].a) {
return false;
}
}
Expand All @@ -317,16 +321,20 @@ static bool Packer_PackContainerAt(
// data to avoid anything else taking this position.
int source_page_index =
container->tex_infos->tpage - m_Data->level_page_count;
uint8_t *source_page = m_Data->source_pages + source_page_index * PAGE_SIZE;
uint8_t *level_page = m_Data->level_pages + page->index * PAGE_SIZE;
RGBA_8888 *source_page =
m_Data->source_pages + source_page_index * PAGE_SIZE;
RGBA_8888 *level_page = m_Data->level_pages + page->index * PAGE_SIZE;

int old_pixel, new_pixel;
for (int y = 0; y < container->bounds->h; y++) {
for (int x = 0; x < container->bounds->w; x++) {
old_pixel = (container->bounds->y + y) * PAGE_WIDTH
+ container->bounds->x + x;
new_pixel = (y_pos + y) * PAGE_WIDTH + x_pos + x;
page->data[new_pixel] = 1;
page->data[new_pixel].r = 1;
page->data[new_pixel].g = 1;
page->data[new_pixel].b = 1;
page->data[new_pixel].a = 255;
level_page[new_pixel] = source_page[old_pixel];
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/game/packer.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "global/types.h"

#include <stdbool.h>
#include <stdint.h>

Expand All @@ -8,8 +10,8 @@ typedef struct PACKER_DATA {
int32_t source_page_count;
int32_t object_count;
int32_t sprite_count;
uint8_t *source_pages;
uint8_t *level_pages;
RGBA_8888 *source_pages;
RGBA_8888 *level_pages;
} PACKER_DATA;

// Attempts to pack the provided source pages into the level pages. Packing
Expand Down
2 changes: 1 addition & 1 deletion src/gfx/3d/3d_renderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ int GFX_3D_Renderer_RegisterTexturePage(
assert(renderer);
assert(data);
GFX_GL_Texture *texture = GFX_GL_Texture_Create(GL_TEXTURE_2D);
GFX_GL_Texture_Load(texture, data, width, height, GL_RGBA, GL_BGRA);
GFX_GL_Texture_Load(texture, data, width, height, GL_RGBA, GL_RGBA);

int texture_num = GFX_NO_TEXTURE;
for (int i = 0; i < GFX_MAX_TEXTURES; i++) {
Expand Down
3 changes: 2 additions & 1 deletion src/global/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1838,7 +1838,8 @@ typedef struct LEVEL_INFO {
int32_t static_count;
int32_t texture_count;
int32_t texture_page_count;
uint8_t *texture_page_ptrs;
uint8_t *texture_old_page_ptrs;
RGBA_8888 *texture_page_ptrs;
int16_t *floor_data;
int32_t anim_texture_range_count;
int32_t item_count;
Expand Down
2 changes: 1 addition & 1 deletion src/global/vars.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ int16_t *g_MeshBase = NULL;
int16_t **g_Meshes = NULL;
OBJECT_INFO g_Objects[O_NUMBER_OF] = { 0 };
STATIC_INFO g_StaticObjects[STATIC_NUMBER_OF] = { 0 };
uint8_t *g_TexturePagePtrs[MAX_TEXTPAGES] = { NULL };
RGBA_8888 *g_TexturePagePtrs[MAX_TEXTPAGES] = { NULL };
int16_t g_RoomCount = 0;
int32_t g_LevelItemCount = 0;
int32_t g_NumberBoxes = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/global/vars.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ extern int16_t *g_MeshBase;
extern int16_t **g_Meshes;
extern OBJECT_INFO g_Objects[O_NUMBER_OF];
extern STATIC_INFO g_StaticObjects[STATIC_NUMBER_OF];
extern uint8_t *g_TexturePagePtrs[MAX_TEXTPAGES];
extern RGBA_8888 *g_TexturePagePtrs[MAX_TEXTPAGES];
extern int16_t g_RoomCount;
extern int32_t g_LevelItemCount;
extern int32_t g_NumberBoxes;
Expand Down
16 changes: 6 additions & 10 deletions src/specific/s_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include <assert.h>
#include <stddef.h>
#include <string.h>

#define CLIP_VERTCOUNT_SCALE 4
#define VBUF_VISIBLE(a, b, c) \
Expand Down Expand Up @@ -1258,16 +1259,11 @@ void S_Output_DownloadTextures(int32_t pages)
bool result = GFX_2D_Surface_Lock(m_TextureSurfaces[i], &surface_desc);
S_Output_CheckError(result);

uint32_t *output_ptr = surface_desc.pixels;
uint8_t *input_ptr = g_TexturePagePtrs[i];
for (int j = 0; j < surface_desc.width * surface_desc.height; j++) {
uint8_t pal_idx = *input_ptr++;
// first color in the palette is chroma key, make it transparent
uint8_t alpha = pal_idx == 0 ? 0 : 0xFF;
RGB_888 pix = S_Output_GetPaletteColor(pal_idx);
*output_ptr++ =
pix.b | (pix.g << 8) | (pix.r << 16) | (alpha << 24);
}
RGBA_8888 *output_ptr = surface_desc.pixels;
RGBA_8888 *input_ptr = g_TexturePagePtrs[i];
memcpy(
output_ptr, input_ptr,
surface_desc.width * surface_desc.height * sizeof(RGBA_8888));

result = GFX_2D_Surface_Unlock(m_TextureSurfaces[i]);
S_Output_CheckError(result);
Expand Down

0 comments on commit c769439

Please sign in to comment.