From c4053cd8b7fd250b9bc2394b8dfc32aba4b48237 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Mon, 6 Apr 2026 21:45:05 -0500 Subject: [PATCH] load files from .pack file --- .gitignore | 3 +- Makefile | 40 ++++++---------- filenames.txt | 5 ++ include/file.h | 5 ++ include/pack.h | 19 ++++++++ src/file.cpp | 39 ++++++++++++++++ src/main.cpp | 62 ++++++++++--------------- src/pack.s | 5 ++ tool/Makefile | 5 ++ tool/pack_file | Bin 0 -> 16368 bytes tool/pack_file.cpp | 112 +++++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 230 insertions(+), 65 deletions(-) create mode 100644 filenames.txt create mode 100644 include/file.h create mode 100644 include/pack.h create mode 100644 src/file.cpp create mode 100644 src/pack.s create mode 100644 tool/Makefile create mode 100755 tool/pack_file create mode 100644 tool/pack_file.cpp diff --git a/.gitignore b/.gitignore index 5a58160..de46c10 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .gdb_history *.spv *.o -main \ No newline at end of file +main +*.pack \ No newline at end of file diff --git a/Makefile b/Makefile index 46ed02f..8bdfd35 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ CC=$(PREFIX)gcc CXX=$(PREFIX)g++ OBJCOPY=$(PREFIX)objcopy +AS=$(PREFIX)as OBJARCH = elf64-x86-64 @@ -30,44 +31,24 @@ endif OBJS = \ src/main.o \ - src/volk/volk.o - -BINS = \ - index.idx.o \ - position_normal_texture.vtx.o \ - sprite.data.o - -SHADERS = \ - shader/triangle.vs.spv.o \ - shader/triangle.ps.spv.o + src/volk/volk.o \ + src/file.o \ + src/pack.o LIBS = \ ../SDL3-dist/lib64/libSDL3.a all: main -define BUILD_BINARY_O - $(OBJCOPY) -I binary -O $(OBJARCH) $< $@ -endef - -%.vtx.o: %.vtx - $(BUILD_BINARY_O) - -%.idx.o: %.idx - $(BUILD_BINARY_O) - -%.spv.o: %.spv - $(BUILD_BINARY_O) - -%.data.o: %.data - $(BUILD_BINARY_O) - %.o: %.c $(CC) $(ARCH) $(CSTD) $(CFLAGS) $(FLAGS) $(OPT) $(DEBUG) -c $< -o $@ %.o: %.cpp $(CXX) $(ARCH) $(CXXSTD) $(CFLAGS) $(FLAGS) $(OPT) $(DEBUG) -c $< -o $@ +%.o: %.s + $(AS) $< -o $@ + main: $(OBJS) $(LIBS) $(BINS) $(SHADERS) $(CC) $(ARCH) $(LDFLAGS) $(FLAGS) $(OPT) $(DEBUG) $^ -o $@ @@ -77,6 +58,13 @@ main: $(OBJS) $(LIBS) $(BINS) $(SHADERS) %.ps.spv: %.hlsl ../dxc/bin/dxc -spirv -T ps_6_1 -E PSMain -fspv-target-env=vulkan1.3 $< -Fo $@ +tool/pack_file: tool/pack_file.cpp + make -C tool pack_file + +PACK_FILENAMES = $(shell cat filenames.txt) +files.pack: tool/pack_file $(PACK_FILENAMES) filenames.txt + ./tool/pack_file $@ $(PACK_FILENAMES) + .SUFFIXES: .INTERMEDIATE: .SECONDARY: diff --git a/filenames.txt b/filenames.txt new file mode 100644 index 0000000..75a1c2d --- /dev/null +++ b/filenames.txt @@ -0,0 +1,5 @@ +shader/triangle.vs.spv +shader/triangle.ps.spv +index.idx +position_normal_texture.vtx +sprite.data diff --git a/include/file.h b/include/file.h new file mode 100644 index 0000000..e9fda03 --- /dev/null +++ b/include/file.h @@ -0,0 +1,5 @@ +#pragma once + +namespace file { + void const * open(const char * r_filename, uint32_t * out_size); +} 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/src/file.cpp b/src/file.cpp new file mode 100644 index 0000000..2f14cbb --- /dev/null +++ b/src/file.cpp @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include + +#include "pack.h" +#include "file.h" + +extern "C" { + extern uint8_t const _files_pack_start[]; + extern uint8_t const _files_pack_end[]; +}; + +namespace file { + + void const * open(const char * r_filename, uint32_t * out_size) + { + fprintf(stderr, "(pack) filename: %s\n", r_filename); + + pack::header const * header = (pack::header const *)&_files_pack_start[0]; + if (header->magic != pack::magic_value) { + fprintf(stderr, "invalid header magic: %08x expected magic value: %08x\n", header->magic, pack::magic_value); + exit(EXIT_FAILURE); + } + ptrdiff_t data = (ptrdiff_t)&_files_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); + exit(EXIT_FAILURE); + } + +} diff --git a/src/main.cpp b/src/main.cpp index fa5fb78..fa624e3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,34 +8,7 @@ #include "directxmath/directxmath.h" #include "new.h" - -extern "C" { - extern uint8_t const _binary_position_normal_texture_vtx_start[]; - extern void * const _binary_position_normal_texture_vtx_size; - extern uint8_t const _binary_index_idx_start[]; - extern void * const _binary_index_idx_size; - - extern uint8_t const _binary_shader_triangle_vs_spv_start[]; - extern void * const _binary_shader_triangle_vs_spv_size; - extern uint8_t const _binary_shader_triangle_ps_spv_start[]; - extern void * const _binary_shader_triangle_ps_spv_size; - - extern uint8_t const _binary_sprite_data_start[]; - extern void * const _binary_sprite_data_size; -} - -#define vtx_start _binary_position_normal_texture_vtx_start -#define vtx_size (size_t)(&_binary_position_normal_texture_vtx_size) -#define idx_start _binary_index_idx_start -#define idx_size (size_t)(&_binary_index_idx_size) - -#define vs_start _binary_shader_triangle_vs_spv_start -#define vs_size (size_t)(&_binary_shader_triangle_vs_spv_size) -#define ps_start _binary_shader_triangle_ps_spv_start -#define ps_size (size_t)(&_binary_shader_triangle_ps_spv_size) - -#define sprite_start _binary_sprite_data_start -#define sprite_size (size_t)(&_binary_sprite_data_size) +#include "file.h" #define SDL_CHECK(f) \ { \ @@ -512,8 +485,13 @@ int main() // mesh ////////////////////////////////////////////////////////////////////// - VkDeviceSize vtxBufferSize{ vtx_size }; - VkDeviceSize idxBufferSize{ idx_size }; + uint32_t vertexSize; + void const * vertexStart = file::open("position_normal_texture.vtx", &vertexSize); + uint32_t indexSize; + void const * indexStart = file::open("index.idx", &indexSize); + + VkDeviceSize vtxBufferSize{ vertexSize }; + VkDeviceSize idxBufferSize{ indexSize }; VkBufferCreateInfo vertexIndexBufferCreateInfo{ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .size = vtxBufferSize + idxBufferSize, @@ -538,8 +516,8 @@ int main() void * vertexIndexMappedData; VK_CHECK(vkMapMemory(device, vertexIndexBufferMemory, 0, vertexIndexBufferCreateInfo.size, 0, &vertexIndexMappedData)); - memcpy((void *)(((ptrdiff_t)vertexIndexMappedData) + 0), vtx_start, vtx_size); - memcpy((void *)(((ptrdiff_t)vertexIndexMappedData) + vtx_size), idx_start, idx_size); + memcpy((void *)(((ptrdiff_t)vertexIndexMappedData) + 0), vertexStart, vertexSize); + memcpy((void *)(((ptrdiff_t)vertexIndexMappedData) + vertexSize), indexStart, indexSize); vkUnmapMemory(device, vertexIndexBufferMemory); ////////////////////////////////////////////////////////////////////// @@ -673,10 +651,13 @@ int main() // texture transfer: source buffer + uint32_t spriteSize; + void const * spriteStart = file::open("sprite.data", &spriteSize); + VkBuffer textureSourceBuffer{}; VkBufferCreateInfo textureSourceBufferCreateInfo{ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = sprite_size, + .size = spriteSize, .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT }; VK_CHECK(vkCreateBuffer(device, &textureSourceBufferCreateInfo, nullptr, &textureSourceBuffer)); @@ -697,7 +678,7 @@ int main() void * textureSourceMappedData; VK_CHECK(vkMapMemory(device, textureSourceBufferMemory, 0, textureSourceBufferCreateInfo.size, 0, &textureSourceMappedData)); - memcpy((void *)(((ptrdiff_t)textureSourceMappedData) + 0), sprite_start, sprite_size); + memcpy((void *)(((ptrdiff_t)textureSourceMappedData) + 0), spriteStart, spriteSize); vkUnmapMemory(device, textureSourceBufferMemory); VkFenceCreateInfo textureFenceCreateInfo{ @@ -872,18 +853,23 @@ int main() // shaders ////////////////////////////////////////////////////////////////////// + uint32_t triangleVSSize; + void const * triangleVSStart = file::open("shader/triangle.vs.spv", &triangleVSSize); + uint32_t trianglePSSize; + void const * trianglePSStart = file::open("shader/triangle.ps.spv", &trianglePSSize); + VkShaderModuleCreateInfo vertexShaderModuleCreateInfo{ .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .codeSize = vs_size, - .pCode = (uint32_t *)vs_start + .codeSize = triangleVSSize, + .pCode = (uint32_t *)triangleVSStart }; VkShaderModule vertexShaderModule{}; VK_CHECK(vkCreateShaderModule(device, &vertexShaderModuleCreateInfo, nullptr, &vertexShaderModule)); VkShaderModuleCreateInfo pixelShaderModuleCreateInfo{ .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .codeSize = ps_size, - .pCode = (uint32_t *)ps_start + .codeSize = trianglePSSize, + .pCode = (uint32_t *)trianglePSStart }; VkShaderModule pixelShaderModule{}; VK_CHECK(vkCreateShaderModule(device, &pixelShaderModuleCreateInfo, nullptr, &pixelShaderModule)); diff --git a/src/pack.s b/src/pack.s new file mode 100644 index 0000000..ef3403f --- /dev/null +++ b/src/pack.s @@ -0,0 +1,5 @@ + .global _files_pack_start + .global _files_pack_end +_files_pack_start: + .incbin "files.pack" +_files_pack_end: diff --git a/tool/Makefile b/tool/Makefile new file mode 100644 index 0000000..54f1ec5 --- /dev/null +++ b/tool/Makefile @@ -0,0 +1,5 @@ +OPT = -O2 +CFLAGS = -I../include + +pack_file: pack_file.cpp + g++ -o $@ $(OPT) $(CFLAGS) $^ diff --git a/tool/pack_file b/tool/pack_file new file mode 100755 index 0000000000000000000000000000000000000000..7faab6640fcb2317415e56653d21b69fc46fcb36 GIT binary patch literal 16368 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 literal 0 HcmV?d00001 diff --git a/tool/pack_file.cpp b/tool/pack_file.cpp new file mode 100644 index 0000000..ecab6ea --- /dev/null +++ b/tool/pack_file.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); +}