load files from .pack file

This commit is contained in:
Zack Buhman 2026-04-06 21:45:05 -05:00
parent cad2532e04
commit c4053cd8b7
11 changed files with 230 additions and 65 deletions

3
.gitignore vendored
View File

@ -1,4 +1,5 @@
.gdb_history
*.spv
*.o
main
main
*.pack

View File

@ -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:

5
filenames.txt Normal file
View File

@ -0,0 +1,5 @@
shader/triangle.vs.spv
shader/triangle.ps.spv
index.idx
position_normal_texture.vtx
sprite.data

5
include/file.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
namespace file {
void const * open(const char * r_filename, uint32_t * out_size);
}

19
include/pack.h Normal file
View File

@ -0,0 +1,19 @@
#include <stdint.h>
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;
}

39
src/file.cpp Normal file
View File

@ -0,0 +1,39 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#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);
}
}

View File

@ -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));

5
src/pack.s Normal file
View File

@ -0,0 +1,5 @@
.global _files_pack_start
.global _files_pack_end
_files_pack_start:
.incbin "files.pack"
_files_pack_end:

5
tool/Makefile Normal file
View File

@ -0,0 +1,5 @@
OPT = -O2
CFLAGS = -I../include
pack_file: pack_file.cpp
g++ -o $@ $(OPT) $(CFLAGS) $^

BIN
tool/pack_file Executable file

Binary file not shown.

112
tool/pack_file.cpp Normal file
View File

@ -0,0 +1,112 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <stdlib.h>
#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);
}