asset packer completed

This commit is contained in:
Matthew 2025-04-07 22:26:13 +10:00
parent 6984296e0c
commit d9ec3f4be2
2 changed files with 213 additions and 37 deletions

View File

@ -11,6 +11,7 @@
#include "game.c" #include "game.c"
#define FWrite(buf, size, count, file) ((size) * (fwrite(buf, size, count, file))) #define FWrite(buf, size, count, file) ((size) * (fwrite(buf, size, count, file)))
#define FRead(buf, size, count, file) ((size) * (fread(buf, size, count, file)))
#if __linux__ #if __linux__
b32 ChangeDir(c8 *dir) b32 ChangeDir(c8 *dir)
@ -80,6 +81,36 @@ b8 DirVisible(c8 *dir_name)
# error Not yet implemented # error Not yet implemented
#endif #endif
u64 FileLength(FILE *file)
{
Assert(fseek(file, 0, SEEK_END) == 0, "fseek failure");
return (u64)ftell(file);
}
u64 WriteData(void *buf, u64 pos, u64 size, FILE *file)
{
Assert(fseek(file, pos, SEEK_SET) == 0, "WriteData fseek failure");
return FWrite(buf, size, 1, file);
}
u64 ReadData(void *buf, u64 pos, u64 size, FILE *file)
{
Assert(fseek(file, pos, SEEK_SET) == 0, "ReadData fseek failure");
return FRead(buf, size, 1, file);
}
FILE *OpenFile(c8 *name, c8 *mode)
{
FILE *file = fopen(name, mode);
Assert(file != NULL, "OpenFile: file is null");
return file;
}
void CloseFile(FILE *file)
{
Assert(fclose(file) != EOF, "Error closing file");
}
void SetArrayLookups() void SetArrayLookups()
{ {
for (i32 i = 0; i < Len(g_Shader_File_Map); i++) for (i32 i = 0; i < Len(g_Shader_File_Map); i++)
@ -112,33 +143,33 @@ i32 WriteHeader(FILE *file, FileHeader *header)
return offset; return offset;
} }
void MoveToShaderDir(c8 *return_dir) void MoveToShaderDir(c8 **return_dir)
{ {
if (DirVisible("build")) if (DirVisible("build"))
{ {
Assert(ChangeDir("./build/shaders/glsl") == 0, "Unable to change to shader directory"); Assert(ChangeDir("./build/shaders/glsl") == 0, "Unable to change to shader directory");
return_dir = "../../.."; *return_dir = "../../..";
} }
else if (DirVisible("shaders")) else if (DirVisible("shaders"))
{ {
Assert(ChangeDir("./shaders/glsl") == 0 , "Unable to change to shader directory"); Assert(ChangeDir("./shaders/glsl") == 0 , "Unable to change to shader directory");
return_dir = "../.."; *return_dir = "../..";
} }
else else
Assert(false, "Unable to find shader directory"); Assert(false, "Unable to find shader directory");
} }
void MoveToTextureDir(c8 *return_dir) void MoveToTextureDir(c8 **return_dir)
{ {
if (DirVisible("assets")) if (DirVisible("assets"))
{ {
Assert(ChangeDir("./assets") == 0, "Unable to change to assets directory"); Assert(ChangeDir("./assets") == 0, "Unable to change to assets directory");
return_dir = ".."; *return_dir = "..";
} }
if (DirVisible("shaders")) else if (DirVisible("shaders"))
{ {
Assert(ChangeDir("../assets") == 0, "Unable to change to assets directory"); Assert(ChangeDir("../assets") == 0, "Unable to change to assets directory");
return_dir = "../build"; *return_dir = "../build";
} }
else else
Assert(false, "Unable to find assets directory"); Assert(false, "Unable to find assets directory");
@ -155,7 +186,7 @@ void InitHeader(FileHeader *header)
header->tag_counts[SHADER_ASSET] = 0; header->tag_counts[SHADER_ASSET] = 0;
header->asset_counts[TEXTURE_ASSET] = TEXTURE_ASSET_MAX; header->asset_counts[TEXTURE_ASSET] = TEXTURE_ASSET_MAX;
header->tag_counts[TEXTURE_ASSET] = TEXTURE_ASSET_MAX; header->tag_counts[TEXTURE_ASSET] = TEXTURE_ASSET_TAG_MAX;
header->asset_counts[SOUND_ASSET] = SOUND_ASSET_MAX; header->asset_counts[SOUND_ASSET] = SOUND_ASSET_MAX;
header->tag_counts[SOUND_ASSET] = SOUND_ASSET_TAG_MAX; header->tag_counts[SOUND_ASSET] = SOUND_ASSET_TAG_MAX;
@ -187,10 +218,9 @@ void InitHeader(FileHeader *header)
void PackFiles(Arena *arena, FileHeader *header) void PackFiles(Arena *arena, FileHeader *header)
{ {
FILE *file = fopen("assets.sgp", "w+"); FILE *file = OpenFile("assets.sgp", "w+");
Assert(file != NULL, "File is null");
Assert(fwrite(header, sizeof(FileHeader), 1, file) == 1, "Unable to write file header"); u64 file_pos = WriteData(header, 0, sizeof(FileHeader), file);
u64 data_offset = 0; u64 data_offset = 0;
for (u32 i = 0; i < ASSET_TYPE_MAX; i++) for (u32 i = 0; i < ASSET_TYPE_MAX; i++)
@ -204,9 +234,9 @@ void PackFiles(Arena *arena, FileHeader *header)
data_offset = asset_offset; data_offset = asset_offset;
} }
c8 *return_dir = ""; c8 *return_dir = ".";
u32 file_count; u32 file_count;
MoveToShaderDir(return_dir); MoveToShaderDir(&return_dir);
AssetFile *shader_assets = MakeArray(arena, AssetFile, SHADER_ASSET_MAX); AssetFile *shader_assets = MakeArray(arena, AssetFile, SHADER_ASSET_MAX);
for (u32 i = 0; i < SHADER_ASSET_MAX; i++) for (u32 i = 0; i < SHADER_ASSET_MAX; i++)
@ -215,27 +245,175 @@ void PackFiles(Arena *arena, FileHeader *header)
Printfln("Packing file: %s...", asset_name); Printfln("Packing file: %s...", asset_name);
FILE *asset_file = fopen(asset_name, "r"); FILE *asset_file = OpenFile(asset_name, "r");
Assert(asset_file != NULL, "Asset file is null"); u64 file_size = FileLength(asset_file);
int ch = getc(asset_file); u8 *file_data = MakeArray(arena, u8, file_size);
Assert(ch != EOF, "File begins with EOF"); ReadData(file_data, 0, file_size, asset_file);
while (ch != EOF) u64 prev_offset = data_offset;
data_offset += WriteData(file_data, data_offset, file_size, file);
Assert((data_offset - prev_offset) == file_size, "File write size invalid");
shader_assets[i].data_offset = prev_offset;
shader_assets[i].len = file_size;
CloseFile(asset_file);
}
Assert(ChangeDir(return_dir) == 0, "Unable to return to previous directory");
MoveToTextureDir(&return_dir);
AssetFile *texture_assets = MakeArray(arena, AssetFile, TEXTURE_ASSET_MAX);
for (u32 i = 0; i < TEXTURE_ASSET_MAX; i++)
{
c8 *asset_name = g_Texture_File_Names[i];
Printfln("Packing file: %s...", asset_name);
FILE *asset_file = OpenFile(asset_name, "r");
u64 file_size = FileLength(asset_file);
u8 *file_data = MakeArray(arena, u8, file_size);
ReadData(file_data, 0, file_size, asset_file);
u64 prev_offset = data_offset;
Printfln("data_offset %llu", data_offset);
data_offset += WriteData(file_data, data_offset, file_size, file);
Assert((data_offset - prev_offset) == file_size, "File write size invalid");
texture_assets[i].data_offset = prev_offset;
texture_assets[i].len = file_size;
CloseFile(asset_file);
}
WriteData(shader_assets, header->asset_offsets[SHADER_ASSET], sizeof(AssetFile)*SHADER_ASSET_MAX, file);
WriteData(texture_assets, header->asset_offsets[TEXTURE_ASSET], sizeof(AssetFile)*TEXTURE_ASSET_MAX, file);
FileLength(file);
ChangeDir(return_dir);
}
void PrintBytes(u8 *bytes, u64 len)
{
return;
u32 count = 0;
while (count + 8 < len)
{
Printfln("%#02X %#02X %#02X %#02X %#02X %#02X %#02X %#02X", bytes[count], bytes[count+1], bytes[count+2], bytes[count+3],
bytes[count+4], bytes[count+5], bytes[count+6], bytes[count+7]);
count += 8;
}
while (count < len)
{
Printf("%u", bytes[count]);
count += 1;
}
}
static inline void TestAssetIsCorrect(Arena *arena, c8 *file_name, AssetFile *file_info, FILE *file)
{
Printfln("Testing file %s...", file_name);
FILE *asset_file = OpenFile(file_name, "r");
u64 size = FileLength(asset_file);
u8 *file_data = MakeArray(arena, u8, size);
u64 write_count = ReadData(file_data, 0, size, asset_file);
Assert(write_count == size, "Incorrect asset size retrieved");
Printfln("len %llu size %llu", file_info->len, size);
Assert(file_info->len == size, "file length incorrect");
u8 *packed_asset = MakeArray(arena, u8, file_info->len);
ReadData(packed_asset, file_info->data_offset, file_info->len, file);
for (u64 i = 0; i < size; i++)
{
Assert(file_data[i] == packed_asset[i], "Asset file data is invalid");
}
CloseFile(asset_file);
}
void TestAssetPack(Arena *arena)
{
FILE *file = OpenFile("assets.sgp", "r");
FileHeader header;
i64 offset = FRead(&header, sizeof(FileHeader), 1, file);
Assert(header.magic_num == CreateMagicValue('s', 't', 'e', 'g'), "Magic number is incorrect");
Assert(header.version == FILE_VERSION, "File version is incorrect");
Assert(header.tag_counts[SHADER_ASSET] == 0, "Shader tag count incorrect");
Assert(header.asset_counts[SHADER_ASSET] == SHADER_ASSET_MAX, "Shader count incorrect");
Assert(header.tag_counts[TEXTURE_ASSET] == TEXTURE_ASSET_TAG_MAX, "Texture tag count incorrect");
Assert(header.asset_counts[TEXTURE_ASSET] == TEXTURE_ASSET_MAX, "Texture count incorrect");
Assert(header.tag_counts[SOUND_ASSET] == SOUND_ASSET_TAG_MAX, "Sound tag count incorrect");
Assert(header.asset_counts[SOUND_ASSET] == SOUND_ASSET_MAX, "Sound count incorrect");
Assert(header.tag_counts[MODEL_ASSET] == MODEL_ASSET_TAG_MAX, "Model tag count incorrect");
Assert(header.asset_counts[MODEL_ASSET] == MODEL_ASSET_MAX, "Model count incorrect");
AssetTag *tags[ASSET_TYPE_MAX];
AssetFile *files[ASSET_TYPE_MAX];
for (u32 i = 0; i < ASSET_TYPE_MAX; i++)
{
if (header.tag_counts[i] > 0)
{ {
putc(ch, file); tags[i] = MakeArray(arena, AssetTag, header.tag_counts[i]);
ch = getc(asset_file); ReadData(tags[i], header.tag_offsets[i], sizeof(AssetTag)*header.tag_counts[i], file);
} }
shader_assets[i].data_offset = data_offset; if (header.asset_counts[i] > 0)
shader_assets[i].asset_id = i; {
files[i] = MakeArray(arena, AssetFile, header.asset_counts[i]);
Printfln("Reading asset info from %llu...", header.asset_offsets[i]);
ReadData(files[i], header.asset_offsets[i], sizeof(AssetFile)*header.asset_counts[i], file);
}
}
data_offset = (u64)ftell(file); for (u32 i = 0; i < SHADER_ASSET_MAX; i++)
{
Printfln("offset %llu len %llu", files[SHADER_ASSET][i].data_offset, files[SHADER_ASSET][i].len);
}
for (u32 i = 0; i < TEXTURE_ASSET_MAX; i++)
{
Printfln("offset %llu len %llu", files[TEXTURE_ASSET][i].data_offset, files[TEXTURE_ASSET][i].len);
}
c8 *return_dir = ".";
MoveToShaderDir(&return_dir);
for (u32 i = 0; i < SHADER_ASSET_MAX; i++)
{
TestAssetIsCorrect(arena, g_Shader_File_Names[i], &files[SHADER_ASSET][i], file);
}
ChangeDir(return_dir);
MoveToTextureDir(&return_dir);
for (u32 i = 0; i < TEXTURE_ASSET_MAX; i++)
{
TestAssetIsCorrect(arena, g_Texture_File_Names[i], &files[TEXTURE_ASSET][i], file);
} }
} }
int main(int argc, c8 **argv) int main(int argc, c8 **argv)
{ {
Printfln("Header: %d", sizeof(FileHeader));
SetArrayLookups(); SetArrayLookups();
void *mem = MemAllocZeroed(GB(1)); void *mem = MemAllocZeroed(GB(1));
@ -247,17 +425,9 @@ int main(int argc, c8 **argv)
FileHeader header = {}; FileHeader header = {};
InitHeader(&header); InitHeader(&header);
PackFiles(arena, &header);
c8 *return_dir;
c8 **asset_names[ASSET_TYPE_MAX];
Assert(fseek(file, 0, SEEK_SET) == 0, "error seeking file");
Assert(fclose(file) != EOF, "error closing file"); CloseFile(file);
TestAssetPack(arena);
} }

View File

@ -30,7 +30,7 @@
# include <dirent.h> # include <dirent.h>
#endif #endif
#define CreateMagicValue(a, b, c, d) (u32)(a << 24) | (u32)(a << 16) | (u32)(a << 8) | (u32)(a) #define CreateMagicValue(a, b, c, d) ((u32)(d << 24) | (u32)(c << 16) | (u32)(b << 8) | (u32)(a))
#define FILE_VERSION 0 #define FILE_VERSION 0
typedef struct AssetTag_t typedef struct AssetTag_t
@ -42,7 +42,7 @@ typedef struct AssetTag_t
typedef struct AssetFile_t typedef struct AssetFile_t
{ {
u64 data_offset; u64 data_offset;
u32 asset_id; u64 len;
} AssetFile; } AssetFile;
typedef struct AssetHeader_t typedef struct AssetHeader_t
@ -92,3 +92,9 @@ u8 **GetFileNamesInDir(Arena *arena, u32 *count);
b8 DirVisible(c8 *dir); b8 DirVisible(c8 *dir);
void InitHeader(FileHeader *header); void InitHeader(FileHeader *header);
i32 WriteHeader(FILE *file, FileHeader *header); i32 WriteHeader(FILE *file, FileHeader *header);
FILE *OpenFile(c8 *name, c8 *mode);
void CloseFile(FILE *file);
u64 FileLength(FILE *file);
u64 WriteData(void *buf, u64 pos, u64 size, FILE *file);
u64 ReadData(void *buf, u64 pos, u64 size, FILE *file);
static inline void TestAssetIsCorrect(Arena *arena, c8 *file_name, AssetFile *file_info, FILE *file);