From d88cb808ff71ee53c62a015cf7e40042a79617f6 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Sat, 21 Mar 2026 14:39:02 -0500 Subject: [PATCH] file: compile-time option to read files from 'pack file' --- .gitignore | 2 + Makefile | 21 ++++++- filenames.txt | 57 +++++++++++++++++++ include/dds_validate.h | 2 +- include/file.h | 14 ++--- include/pack.h | 19 +++++++ include/world/world.h | 5 +- src/collada/scene.cpp | 8 +-- src/dds_validate.cpp | 2 +- src/file.c | 70 ------------------------ src/file.cpp | 109 +++++++++++++++++++++++++++++++++++++ src/flame.cpp | 4 +- src/font/bitmap.cpp | 4 +- src/font/outline.cpp | 4 +- src/minecraft.cpp | 29 +++++----- src/non_block.cpp | 8 +-- src/opengl.cpp | 26 ++++----- src/pack_main.cpp | 112 ++++++++++++++++++++++++++++++++++++++ src/test.cpp | 6 +- src/world/entry_table.cpp | 4 +- src/world/world.cpp | 14 ----- 21 files changed, 375 insertions(+), 145 deletions(-) create mode 100644 filenames.txt create mode 100644 include/pack.h delete mode 100644 src/file.c create mode 100644 src/file.cpp create mode 100644 src/pack_main.cpp diff --git a/.gitignore b/.gitignore index 945629b..14e2268 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ __pycache__ minecraft/region*.lights.vtx minecraft/region*.dump minecraft/gen/map.txt +test.pack +pack_main \ No newline at end of file diff --git a/Makefile b/Makefile index 1c0ab1b..35b6abf 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,9 @@ #PREFIX = x86_64-w64-mingw32- CC=$(PREFIX)gcc CXX=$(PREFIX)g++ +OBJCOPY=$(PREFIX)objcopy + +OBJARCH = elf64-x86-64 OPT = -O0 -march=x86-64-v3 @@ -13,6 +16,9 @@ CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable -Wno-error=unu CFLAGS += -Wno-error=unknown-pragmas -Wno-unknown-pragmas CFLAGS += $(shell pkg-config --cflags glfw3) CFLAGS += -fno-strict-aliasing +ifdef READ_PACK_FILE +CFLAGS += -DREAD_PACK_FILE +endif LDFLAGS += -lm LDFLAGS += $(shell pkg-config --libs glfw3) @@ -56,6 +62,10 @@ OBJS = \ data/scenes/book/book.o \ $(MINECRAFT_OBJS) +ifdef READ_PACK_FILE +OBJS += test.pack.o +endif + all: test.so %.o: %.c @@ -64,8 +74,14 @@ all: test.so %.o: %.cpp $(CXX) $(ARCH) $(CXXSTD) $(CFLAGS) $(OPT) -c $< -o $@ +test.pack: pack_main + ./pack_main $@ $(shell cat filenames.txt) + +test.pack.o: test.pack + $(OBJCOPY) -I binary -O $(OBJARCH) $< $@ + test.so: $(OBJS) - $(CC) $(ARCH) $(OPT) -shared -g $^ -o $@ -lSDL3 + $(CC) $(ARCH) $(OPT) -Wl,-z noexecstack -shared -g $^ -o $@ -lSDL3 main: $(OBJS) src/main.o $(CC) $(ARCH) $(LDFLAGS) $(OPT) -g $^ -o $@ @@ -73,6 +89,9 @@ main: $(OBJS) src/main.o clean: find . -type f ! -name "*.*" -delete +pack_main: src/pack_main.o + $(CC) $(ARCH) $(OPT) -g $^ -o $@ + .SUFFIXES: .INTERMEDIATE: .SECONDARY: diff --git a/filenames.txt b/filenames.txt new file mode 100644 index 0000000..8c4798f --- /dev/null +++ b/filenames.txt @@ -0,0 +1,57 @@ +shader/minecraft.vert +shader/minecraft.frag +minecraft/per_vertex.vtx +minecraft/configuration.idx +minecraft/terrain2.data +minecraft/grandlecturn/region.0.0.instance.vtx +minecraft/grandlecturn/region.0.0.instance.cfg +minecraft/grandlecturn/region.-1.0.instance.vtx +minecraft/grandlecturn/region.-1.0.instance.cfg +minecraft/grandlecturn/region.0.-1.instance.vtx +minecraft/grandlecturn/region.0.-1.instance.cfg +minecraft/grandlecturn/region.-1.-1.instance.vtx +minecraft/grandlecturn/region.-1.-1.instance.cfg +minecraft/grandlecturn/global.lights.vtx +minecraft/grandlecturn/global.dump +minecraft/midnightmeadow/region.0.0.instance.vtx +minecraft/midnightmeadow/region.0.0.instance.cfg +minecraft/midnightmeadow/region.-1.0.instance.vtx +minecraft/midnightmeadow/region.-1.0.instance.cfg +minecraft/midnightmeadow/region.0.-1.instance.vtx +minecraft/midnightmeadow/region.0.-1.instance.cfg +minecraft/midnightmeadow/region.-1.-1.instance.vtx +minecraft/midnightmeadow/region.-1.-1.instance.cfg +minecraft/midnightmeadow/global.lights.vtx +minecraft/midnightmeadow/global.dump +shader/font.vert +shader/font.frag +font/bitmap/terminus_128x64_6x12.data +font/bitmap/terminus_128x128_8x16.data +font/bitmap/terminus_256x128_10x18.data +font/bitmap/terminus_256x128_12x24.data +font/bitmap/terminus_256x256_16x32.data +shader/font.vert +shader/font_outline.frag +font/outline/uncial_antiqua_36.data +shader/pixel_line_art.vert +shader/pixel_line_art.frag +shader/quad.vert +shader/quad.frag +shader/quad.vert +shader/lighting.frag +shader/non_block.vert +shader/non_block.frag +minecraft/non_block.idx +minecraft/non_block.vtx +shader/line_art.vert +shader/line_art.frag +shader/collada/static.vert +shader/collada/generic.frag +shader/collada/skinned.vert +shader/collada/generic.frag +data/scenes/book/book.vtx +data/scenes/book/book.vjw +data/scenes/book/book.idx +shader/flame.vert +shader/flame.frag +minecraft/flame.data diff --git a/include/dds_validate.h b/include/dds_validate.h index 1aa733e..84f718f 100644 --- a/include/dds_validate.h +++ b/include/dds_validate.h @@ -7,4 +7,4 @@ struct DDS_FILE { DDS_HEADER header; }; -DDS_FILE const * dds_validate(void * data, unsigned int size, void ** out_data, int * out_size); +DDS_FILE const * dds_validate(void const * data, unsigned int size, void ** out_data, int * out_size); diff --git a/include/file.h b/include/file.h index a4dca70..db52466 100644 --- a/include/file.h +++ b/include/file.h @@ -1,14 +1,10 @@ #pragma once -#ifdef __cplusplus -extern "C" { -#endif +namespace file { + extern char const * source_path; + extern int source_path_length; -extern char const * g_source_path; -extern int g_source_path_length; + void const * read_file(const char * filename, int * out_size); -void * read_file(const char * filename, int * out_size); - -#ifdef __cplusplus + void free(void const * buf); } -#endif diff --git a/include/pack.h b/include/pack.h new file mode 100644 index 0000000..9c96fb6 --- /dev/null +++ b/include/pack.h @@ -0,0 +1,19 @@ +#include + +namespace pack { + struct file_entry { + char filename[128]; + uint32_t offset; + uint32_t size; + }; + + struct header { + uint32_t magic; + uint32_t header_size; + uint32_t entry_count; + file_entry entry[0]; + }; + static_assert((sizeof (header)) == 12); + + const uint32_t magic_value = 0x037c2dc0; +} diff --git a/include/world/world.h b/include/world/world.h index 6425649..26c22b9 100644 --- a/include/world/world.h +++ b/include/world/world.h @@ -20,9 +20,8 @@ namespace world { struct world_id { enum { - LOVE2DWORLD = 0, - GRANDLECTURN = 1, - MIDNIGHTMEADOW = 2, + GRANDLECTURN = 0, + MIDNIGHTMEADOW = 1, }; }; diff --git a/src/collada/scene.cpp b/src/collada/scene.cpp index 2b79c3a..dbab6ed 100644 --- a/src/collada/scene.cpp +++ b/src/collada/scene.cpp @@ -222,14 +222,14 @@ namespace collada::scene { static unsigned int load_vertex_buffer(const char * filename) { int size; - void * data = read_file(filename, &size); + void const * data = file::read_file(filename, &size); assert(data != NULL); unsigned int vertex_buffer; glGenBuffers(1, &vertex_buffer); glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); - free(data); + file::free(data); glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -239,7 +239,7 @@ namespace collada::scene { static unsigned int load_index_buffer(const char * filename) { int size; - void * data = read_file(filename, &size); + void const * data = file::read_file(filename, &size); assert(data != NULL); unsigned int index_buffer; @@ -247,7 +247,7 @@ namespace collada::scene { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); - free(data); + file::free(data); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); diff --git a/src/dds_validate.cpp b/src/dds_validate.cpp index a99ff35..0e0a615 100644 --- a/src/dds_validate.cpp +++ b/src/dds_validate.cpp @@ -44,7 +44,7 @@ static inline dds_size_levels dds_mip_total_size(uintptr_t data, return (dds_size_levels){mip_total_size, mip_levels}; } -DDS_FILE const * dds_validate(void * data, unsigned int size, void ** out_data, int * out_size) +DDS_FILE const * dds_validate(void const * data, unsigned int size, void ** out_data, int * out_size) { DDS_FILE const * const dds = (DDS_FILE const *)data; assert(dds->dwMagic == DDS_MAGIC); diff --git a/src/file.c b/src/file.c deleted file mode 100644 index 3e9aa86..0000000 --- a/src/file.c +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "file.h" - -char const * g_source_path = NULL; -int g_source_path_length = 0; - -char const * join_path(char * buf, const char * filename) -{ - if (filename[0] == '/') - return filename; - - int filename_length = strlen(filename); - assert(filename_length + g_source_path_length + 2 < 1024); - - memcpy(buf, g_source_path, g_source_path_length); - buf[g_source_path_length] = '/'; - - memcpy(&buf[g_source_path_length + 1], filename, filename_length); - buf[g_source_path_length + 1 + filename_length] = 0; - return buf; -} - -void * read_file(const char * r_filename, int * out_size) -{ - char tmp[1024]; - char const * filename = join_path(tmp, r_filename); - - FILE * f = fopen(filename, "rb"); - if (f == NULL) { - fprintf(stderr, "fopen(%s): %s\n", filename, strerror(errno)); - return NULL; - } - - int fseek_end_ret = fseek(f, 0, SEEK_END); - if (fseek_end_ret < 0) { - fprintf(stderr, "fseek(%s, SEEK_END): %s\n", filename, strerror(errno)); - return NULL; - } - - long size = ftell(f); - if (size < 0) { - fprintf(stderr, "ftell(%s): %s\n", filename, strerror(errno)); - return NULL; - } - - int fseek_set_ret = fseek(f, 0, SEEK_SET); - if (fseek_set_ret < 0) { - fprintf(stderr, "lseek(%s, SEEK_SET): %s\n", filename, strerror(errno)); - return NULL; - } - rewind(f); - - void * buf = malloc(size); - - size_t read_size = fread(buf, 1, size, f); - if (read_size != size) { - fprintf(stderr, "fread(%s): %s\n", filename, strerror(errno)); - return NULL; - } - - *out_size = size; - - return buf; -} diff --git a/src/file.cpp b/src/file.cpp new file mode 100644 index 0000000..ca24025 --- /dev/null +++ b/src/file.cpp @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include + +#include "file.h" + +namespace file { + char const * source_path = NULL; + int source_path_length = 0; + +#ifdef READ_PACK_FILE +#include "pack.h" + extern "C" { + extern uint8_t const _binary_test_pack_start[]; + extern uint8_t const _binary_test_pack_end[]; + extern int const _binary_test_pack_size; + }; + + void const * read_file(const char * r_filename, int * out_size) + { + pack::header const * header = (pack::header const *)&_binary_test_pack_start[0]; + assert(header->magic == pack::magic_value); + ptrdiff_t data = (ptrdiff_t)&_binary_test_pack_start[header->header_size]; + + for (unsigned int i = 0; i < header->entry_count; i++) { + if (strcmp(header->entry[i].filename, r_filename) == 0) { + *out_size = header->entry[i].size; + return (void const *)(data + header->entry[i].offset); + } + } + fprintf(stderr, "filename not found in pack file %s\n", r_filename); + assert(false); + } + + void free(void const * buf) + { + (void)buf; + } +#else + static char const * join_path(char * buf, const char * filename) + { + if (filename[0] == '/') + return filename; + + int filename_length = strlen(filename); + assert(filename_length + source_path_length + 2 < 1024); + + memcpy(buf, source_path, source_path_length); + buf[source_path_length] = '/'; + + memcpy(&buf[source_path_length + 1], filename, filename_length); + buf[source_path_length + 1 + filename_length] = 0; + return buf; + } + + void const * read_file(const char * r_filename, int * out_size) + { + fprintf(stderr, "r_filename: %s\n", r_filename); + + char tmp[1024]; + char const * filename = join_path(tmp, r_filename); + + FILE * f = fopen(filename, "rb"); + if (f == NULL) { + fprintf(stderr, "fopen(%s): %s\n", filename, strerror(errno)); + return NULL; + } + + int fseek_end_ret = fseek(f, 0, SEEK_END); + if (fseek_end_ret < 0) { + fprintf(stderr, "fseek(%s, SEEK_END): %s\n", filename, strerror(errno)); + return NULL; + } + + size_t size = ftell(f); + if (size < 0) { + fprintf(stderr, "ftell(%s): %s\n", filename, strerror(errno)); + return NULL; + } + + int fseek_set_ret = fseek(f, 0, SEEK_SET); + if (fseek_set_ret < 0) { + fprintf(stderr, "lseek(%s, SEEK_SET): %s\n", filename, strerror(errno)); + return NULL; + } + rewind(f); + + void * buf = malloc(size); + + size_t read_size = fread(buf, 1, size, f); + if (read_size != size) { + fprintf(stderr, "fread(%s): %s\n", filename, strerror(errno)); + return NULL; + } + + *out_size = size; + + return buf; + } + + void free(void const * buf) + { + ::free((void *)buf); + } +#endif +} diff --git a/src/flame.cpp b/src/flame.cpp index bf439f3..1794bc6 100644 --- a/src/flame.cpp +++ b/src/flame.cpp @@ -62,14 +62,14 @@ namespace flame { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); int texture_data_size; - void * texture_data = read_file("minecraft/flame.data", &texture_data_size); + void const * texture_data = file::read_file("minecraft/flame.data", &texture_data_size); assert(texture_data != nullptr); int width = 16; int height = 80; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data); - free(texture_data); + file::free(texture_data); glBindTexture(GL_TEXTURE_2D, 0); diff --git a/src/font/bitmap.cpp b/src/font/bitmap.cpp index 541f2dc..2e9285f 100644 --- a/src/font/bitmap.cpp +++ b/src/font/bitmap.cpp @@ -58,14 +58,14 @@ namespace font::bitmap { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); int texture_data_size; - void * texture_data = read_file(desc.path, &texture_data_size); + void const * texture_data = file::read_file(desc.path, &texture_data_size); assert(texture_data != nullptr); int width = desc.texture_width; int height = desc.texture_height; glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, texture_data); - free(texture_data); + file::free(texture_data); glBindTexture(GL_TEXTURE_2D, 0); diff --git a/src/font/outline.cpp b/src/font/outline.cpp index 374b8dc..2de90ee 100644 --- a/src/font/outline.cpp +++ b/src/font/outline.cpp @@ -45,7 +45,7 @@ namespace font::outline { static inline font load_font(font_desc const& desc) { int font_data_size; - void * font_data = read_file(desc.path, &font_data_size); + void const * font_data = file::read_file(desc.path, &font_data_size); assert(font_data != nullptr); types::font * font = (types::font *)font_data; @@ -72,6 +72,8 @@ namespace font::outline { glBindTexture(GL_TEXTURE_2D, 0); + // font_data intentionally not free'd + return (outline::font){ .texture = texture, .font = font, diff --git a/src/minecraft.cpp b/src/minecraft.cpp index ecc1700..2af9b31 100644 --- a/src/minecraft.cpp +++ b/src/minecraft.cpp @@ -44,8 +44,8 @@ namespace minecraft { static unsigned int texture; - static const int world_count = 3; - static world::state world_state[world_count]; + static const int max_world_count = 10; + static world::state world_state[max_world_count]; world::state * current_world; void load_program() @@ -129,12 +129,12 @@ namespace minecraft { glGenBuffers(1, &per_vertex_buffer); int vertex_buffer_data_size; - void * vertex_buffer_data = read_file("minecraft/per_vertex.vtx", &vertex_buffer_data_size); + void const * vertex_buffer_data = file::read_file("minecraft/per_vertex.vtx", &vertex_buffer_data_size); glBindBuffer(GL_ARRAY_BUFFER, per_vertex_buffer); glBufferData(GL_ARRAY_BUFFER, vertex_buffer_data_size, vertex_buffer_data, GL_STATIC_DRAW); - free(vertex_buffer_data); + file::free(vertex_buffer_data); glBindBuffer(GL_ARRAY_BUFFER, 0); } @@ -144,12 +144,12 @@ namespace minecraft { glGenBuffers(1, &index_buffer); int index_buffer_data_size; - void * index_buffer_data = read_file("minecraft/configuration.idx", &index_buffer_data_size); + void const * index_buffer_data = file::read_file("minecraft/configuration.idx", &index_buffer_data_size); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_buffer_data_size, index_buffer_data, GL_STATIC_DRAW); - free(index_buffer_data); + file::free(index_buffer_data); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } @@ -165,14 +165,14 @@ namespace minecraft { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); int texture_data_size; - void * texture_data = read_file("minecraft/terrain2.data", &texture_data_size); + void const * texture_data = file::read_file("minecraft/terrain2.data", &texture_data_size); assert(texture_data != NULL); int width = 128; int height = 128; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data); - free(texture_data); + file::free(texture_data); glBindTexture(GL_TEXTURE_2D, 0); } @@ -184,21 +184,21 @@ namespace minecraft { static void load_instance_cfg(char const * path, world::instance_cfg_entry * entries) { int data_size; - void * data = read_file(path, &data_size); - printf("%s %d %d %ld\n", path, data_size, world::instance_cfg_length, (sizeof (struct world::instance_cfg_entry))); + void const * data = file::read_file(path, &data_size); assert(data_size == (sizeof (struct world::instance_cfg_entry)) * world::instance_cfg_length); memcpy(entries, data, data_size); + file::free(data); } static void load_per_instance_vertex_buffer(char const * path, unsigned int vertex_buffer) { int vertex_buffer_data_size; - void * vertex_buffer_data = read_file(path, &vertex_buffer_data_size); // vertex_paths[i].vtx + void const * vertex_buffer_data = file::read_file(path, &vertex_buffer_data_size); // vertex_paths[i].vtx glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); //per_instance_vertex_buffers[i] glBufferData(GL_ARRAY_BUFFER, vertex_buffer_data_size, vertex_buffer_data, GL_STATIC_DRAW); - free(vertex_buffer_data); + file::free(vertex_buffer_data); glBindBuffer(GL_ARRAY_BUFFER, 0); } @@ -264,9 +264,8 @@ namespace minecraft { // worlds ////////////////////////////////////////////////////////////////////// - for (int i = 0; i < world_count; i++) { - if (i == 0) - continue; + assert(max_world_count > world::descriptors_length); + for (int i = 0; i < world::descriptors_length; i++) { per_world::load_world(&world::descriptors[i], world_state[i]); } current_world = &world_state[world::world_id::MIDNIGHTMEADOW]; diff --git a/src/non_block.cpp b/src/non_block.cpp index b85e987..d732578 100644 --- a/src/non_block.cpp +++ b/src/non_block.cpp @@ -34,12 +34,12 @@ namespace non_block { glGenBuffers(1, &index_buffer); int index_buffer_data_size; - void * index_buffer_data = read_file("minecraft/non_block.idx", &index_buffer_data_size); + void const * index_buffer_data = file::read_file("minecraft/non_block.idx", &index_buffer_data_size); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_buffer_data_size, index_buffer_data, GL_STATIC_DRAW); - free(index_buffer_data); + file::free(index_buffer_data); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } @@ -49,12 +49,12 @@ namespace non_block { glGenBuffers(1, &per_vertex_buffer); int vertex_buffer_data_size; - void * vertex_buffer_data = read_file("minecraft/non_block.vtx", &vertex_buffer_data_size); + void const * vertex_buffer_data = file::read_file("minecraft/non_block.vtx", &vertex_buffer_data_size); glBindBuffer(GL_ARRAY_BUFFER, per_vertex_buffer); glBufferData(GL_ARRAY_BUFFER, vertex_buffer_data_size, vertex_buffer_data, GL_STATIC_DRAW); - free(vertex_buffer_data); + file::free(vertex_buffer_data); glBindBuffer(GL_ARRAY_BUFFER, 0); } diff --git a/src/opengl.cpp b/src/opengl.cpp index 77c4d2c..5df0866 100644 --- a/src/opengl.cpp +++ b/src/opengl.cpp @@ -81,30 +81,30 @@ unsigned int compile_from_files(char const * vertex_path, char const * fragment_path) { int vertex_source_size = 0; - void * vertex_source = NULL; + void const * vertex_source = NULL; int geometry_source_size = 0; - void * geometry_source = NULL; + void const * geometry_source = NULL; int fragment_source_size = 0; - void * fragment_source = NULL; + void const * fragment_source = NULL; - vertex_source = read_file(vertex_path, &vertex_source_size); + vertex_source = file::read_file(vertex_path, &vertex_source_size); assert(vertex_source != NULL); if (geometry_path != NULL) { - geometry_source = read_file(geometry_path, &geometry_source_size); + geometry_source = file::read_file(geometry_path, &geometry_source_size); assert(geometry_source != NULL); } - fragment_source = read_file(fragment_path, &fragment_source_size); + fragment_source = file::read_file(fragment_path, &fragment_source_size); assert(fragment_source != NULL); unsigned int program = compile((char const *)vertex_source, vertex_source_size, (char const *)geometry_source, geometry_source_size, (char const *)fragment_source, fragment_source_size); - free(vertex_source); - free(geometry_source); - free(fragment_source); + file::free(vertex_source); + file::free(geometry_source); + file::free(fragment_source); return program; } @@ -116,11 +116,11 @@ unsigned int load_uniform_buffer(char const * const path, int * out_size) glBindBuffer(GL_UNIFORM_BUFFER, buffer); int data_size; - void * data = read_file(path, &data_size); + void const * data = file::read_file(path, &data_size); assert(data != NULL); glBufferData(GL_UNIFORM_BUFFER, data_size, data, GL_STATIC_DRAW); - free(data); + file::free(data); glBindBuffer(GL_UNIFORM_BUFFER, 0); @@ -134,7 +134,7 @@ void load_dds_texture_2D(char const * const path) fprintf(stderr, "load DDS texture: %s\n", path); int size; - void * data = read_file(path, &size); + void const * data = file::read_file(path, &size); assert(data != NULL); void * image_data; @@ -150,5 +150,5 @@ void load_dds_texture_2D(char const * const path) image_size, image_data); - free(data); + file::free(data); } diff --git a/src/pack_main.cpp b/src/pack_main.cpp new file mode 100644 index 0000000..ecab6ea --- /dev/null +++ b/src/pack_main.cpp @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include + +#include "pack.h" + +static uint8_t copy_buffer[1024 * 1024]; +static int const copy_buffer_size = (sizeof (copy_buffer)); + +void copy_file(FILE * output, FILE * input, size_t size) +{ + size_t written = 0; + + while (true) { + size_t read_size = fread(copy_buffer, 1, copy_buffer_size, input); + if (read_size == 0) + break; + + size_t write_size = fwrite(copy_buffer, 1, read_size, output); + assert(write_size == read_size); + + written += write_size; + + if (read_size < copy_buffer_size) + break; + } + + assert(written == size); +} + +FILE * file_size(const char * filename, uint32_t * out_size) +{ + FILE * f = fopen(filename, "rb"); + if (f == nullptr) { + fprintf(stderr, "fopen(%s): %s\n", filename, strerror(errno)); + return nullptr; + } + + int fseek_end_ret = fseek(f, 0, SEEK_END); + if (fseek_end_ret < 0) { + fprintf(stderr, "fseek(%s, SEEK_END): %s\n", filename, strerror(errno)); + return nullptr; + } + + long size = ftell(f); + if (size < 0) { + fprintf(stderr, "ftell(%s): %s\n", filename, strerror(errno)); + return nullptr; + } + + int fseek_set_ret = fseek(f, 0, SEEK_SET); + if (fseek_set_ret < 0) { + fprintf(stderr, "fseek(%s, SEEK_SET): %s\n", filename, strerror(errno)); + return nullptr; + } + + *out_size = size; + + return f; +} + +int main(int argc, char const * argv[]) +{ + assert(argc >= 3); + + int files_count = argc - 2; + char const * output_filename = argv[1]; + char const * const * filenames = &argv[2]; + FILE * files[files_count]; + + int header_size = (sizeof (pack::header)) + (sizeof (pack::file_entry)) * files_count; + pack::header * header = (pack::header *)malloc(header_size); + memset(header, 0, header_size); + + header->magic = pack::magic_value; + header->header_size = header_size; + header->entry_count = files_count; + int offset = 0; + + for (int i = 0; i < files_count; i++) { + char const * filename = filenames[i]; + uint32_t size; + FILE * file = file_size(filename, &size); + assert(file != nullptr); + files[i] = file; + int filename_length = strlen(filename); + assert(filename_length <= 127); + memcpy(header->entry[i].filename, filename, filename_length); + header->entry[i].offset = offset; + header->entry[i].size = size; + offset += size; + } + + FILE * fout = fopen(output_filename, "wb"); + if (fout == nullptr) { + fprintf(stderr, "fopen(%s): %s\n", output_filename, strerror(errno)); + return EXIT_FAILURE; + } + + fwrite((void *)header, 1, header_size, fout); + + for (int i = 0; i < files_count; i++) { + copy_file(fout, files[i], header->entry[i].size); + int fclose_ret = fclose(files[i]); + assert(fclose_ret == 0); + } + + int fclose_ret = fclose(fout); + assert(fclose_ret == 0); +} diff --git a/src/test.cpp b/src/test.cpp index 92337c3..beea871 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -116,9 +116,9 @@ extern "C" { void load(const char * source_path) { - g_source_path_length = strlen(source_path); - assert(source_path[g_source_path_length - 1] != '/'); - g_source_path = source_path; + file::source_path_length = strlen(source_path); + assert(source_path[file::source_path_length - 1] != '/'); + file::source_path = source_path; fprintf(stderr, "getproc %p\n", SDL_GL_GetProcAddress); gladLoadGL((GLADloadfunc)SDL_GL_GetProcAddress); diff --git a/src/world/entry_table.cpp b/src/world/entry_table.cpp index a515306..b44b3ea 100644 --- a/src/world/entry_table.cpp +++ b/src/world/entry_table.cpp @@ -16,7 +16,7 @@ namespace world::entry_table { hash_func_t * hash_func) { int global_size; - global_entry_t * entry = (global_entry_t *)read_file(path, &global_size); + global_entry_t const * entry = (global_entry_t const *)file::read_file(path, &global_size); assert(entry != NULL); int entry_table_length = global_size / (sizeof (global_entry_t)); @@ -33,7 +33,7 @@ namespace world::entry_table { memcpy(&entry_table[ix], &entry[i], (sizeof (global_entry_t))); } - free(entry); + file::free(entry); *out_entry_table = entry_table; *out_entry_table_length = entry_table_length; diff --git a/src/world/world.cpp b/src/world/world.cpp index d179727..a436ef6 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -2,13 +2,6 @@ #include "world/inthash.h" namespace world { - static vtx_cfg const love2dworld_vertex_paths[] = { - { "minecraft/love2dworld/region.0.0.instance.vtx", "minecraft/love2dworld/region.0.0.instance.cfg" }, - { "minecraft/love2dworld/region.-1.0.instance.vtx", "minecraft/love2dworld/region.-1.0.instance.cfg" }, - { "minecraft/love2dworld/region.0.-1.instance.vtx", "minecraft/love2dworld/region.0.-1.instance.cfg" }, - { "minecraft/love2dworld/region.-1.-1.instance.vtx", "minecraft/love2dworld/region.-1.-1.instance.cfg" }, - }; - static vtx_cfg const grandlecturn_vertex_paths[] = { { "minecraft/grandlecturn/region.0.0.instance.vtx", "minecraft/grandlecturn/region.0.0.instance.cfg" }, { "minecraft/grandlecturn/region.-1.0.instance.vtx", "minecraft/grandlecturn/region.-1.0.instance.cfg" }, @@ -24,13 +17,6 @@ namespace world { }; descriptor const descriptors[] = { - [world_id::LOVE2DWORLD] = { - .region_count = 4, - .vertex_paths = love2dworld_vertex_paths, - .entry_table_path = "minecraft/love2dworld/global.dump", - .lights_path = "minecraft/love2dworld/global.lights.vtx", - .hash_func = love2dworld_hash, - }, [world_id::GRANDLECTURN] = { .region_count = 4, .vertex_paths = grandlecturn_vertex_paths,