diff --git a/src/packer.c b/src/packer.c index ac9ee95..c3fd737 100644 --- a/src/packer.c +++ b/src/packer.c @@ -11,6 +11,7 @@ #include "game.c" #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__ b32 ChangeDir(c8 *dir) @@ -80,6 +81,36 @@ b8 DirVisible(c8 *dir_name) # error Not yet implemented #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() { for (i32 i = 0; i < Len(g_Shader_File_Map); i++) @@ -112,33 +143,33 @@ i32 WriteHeader(FILE *file, FileHeader *header) return offset; } -void MoveToShaderDir(c8 *return_dir) +void MoveToShaderDir(c8 **return_dir) { if (DirVisible("build")) { Assert(ChangeDir("./build/shaders/glsl") == 0, "Unable to change to shader directory"); - return_dir = "../../.."; + *return_dir = "../../.."; } else if (DirVisible("shaders")) { Assert(ChangeDir("./shaders/glsl") == 0 , "Unable to change to shader directory"); - return_dir = "../.."; + *return_dir = "../.."; } else Assert(false, "Unable to find shader directory"); } -void MoveToTextureDir(c8 *return_dir) +void MoveToTextureDir(c8 **return_dir) { if (DirVisible("assets")) { 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"); - return_dir = "../build"; + *return_dir = "../build"; } else Assert(false, "Unable to find assets directory"); @@ -155,7 +186,7 @@ void InitHeader(FileHeader *header) header->tag_counts[SHADER_ASSET] = 0; 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->tag_counts[SOUND_ASSET] = SOUND_ASSET_TAG_MAX; @@ -187,10 +218,9 @@ void InitHeader(FileHeader *header) void PackFiles(Arena *arena, FileHeader *header) { - FILE *file = fopen("assets.sgp", "w+"); - Assert(file != NULL, "File is null"); + FILE *file = OpenFile("assets.sgp", "w+"); - 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; for (u32 i = 0; i < ASSET_TYPE_MAX; i++) @@ -204,9 +234,9 @@ void PackFiles(Arena *arena, FileHeader *header) data_offset = asset_offset; } - c8 *return_dir = ""; + c8 *return_dir = "."; u32 file_count; - MoveToShaderDir(return_dir); + MoveToShaderDir(&return_dir); AssetFile *shader_assets = MakeArray(arena, AssetFile, SHADER_ASSET_MAX); 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); - FILE *asset_file = fopen(asset_name, "r"); - Assert(asset_file != NULL, "Asset file is null"); + FILE *asset_file = OpenFile(asset_name, "r"); + u64 file_size = FileLength(asset_file); - int ch = getc(asset_file); - Assert(ch != EOF, "File begins with EOF"); + u8 *file_data = MakeArray(arena, u8, file_size); + 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); - ch = getc(asset_file); + tags[i] = MakeArray(arena, AssetTag, header.tag_counts[i]); + ReadData(tags[i], header.tag_offsets[i], sizeof(AssetTag)*header.tag_counts[i], file); } - shader_assets[i].data_offset = data_offset; - shader_assets[i].asset_id = i; + if (header.asset_counts[i] > 0) + { + 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) { + Printfln("Header: %d", sizeof(FileHeader)); + SetArrayLookups(); void *mem = MemAllocZeroed(GB(1)); @@ -247,17 +425,9 @@ int main(int argc, c8 **argv) FileHeader header = {}; InitHeader(&header); - - - c8 *return_dir; - - c8 **asset_names[ASSET_TYPE_MAX]; - - - - - - Assert(fseek(file, 0, SEEK_SET) == 0, "error seeking file"); + PackFiles(arena, &header); - Assert(fclose(file) != EOF, "error closing file"); + CloseFile(file); + + TestAssetPack(arena); } diff --git a/src/packer.h b/src/packer.h index 8527453..2aede4f 100644 --- a/src/packer.h +++ b/src/packer.h @@ -30,7 +30,7 @@ # include #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 typedef struct AssetTag_t @@ -42,7 +42,7 @@ typedef struct AssetTag_t typedef struct AssetFile_t { u64 data_offset; - u32 asset_id; + u64 len; } AssetFile; typedef struct AssetHeader_t @@ -92,3 +92,9 @@ u8 **GetFileNamesInDir(Arena *arena, u32 *count); b8 DirVisible(c8 *dir); void InitHeader(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);