#include "pak.h" #include "aliases.h" #include "darr.h" #include "io.h" #include #include #include #include #define PAK_MAGIC 0x4B41502054535341 #define PAK_MAJOR 1 #define PAK_MINOR 0 #define PAK_PATCH 0 #define PAK_EXT ".pak" struct pak_read { pak_t header; u8 *buf; u8 *toc; u64 assets_length; u8 *assets; }; toc_entry_t *create_toc_entry(const char *name, u64 offset); void write_toc_entry(toc_entry_t *entry, FILE *fp); void write_toc_entries(const toc_t *toc, toc_entry_t **entries, FILE *fp); pak_entry_t *create_pak_entry(u64 data_length); pak_entry_t *create_pak_entry_from_file(FILE *fp); void write_pak_entry(const pak_entry_t *entry, FILE *fp); void write_pak(const pak_t *pak, toc_entry_t **toc_entries, pak_entry_t **pak_entries, FILE *fp); bool create_asset_pack(const char *dirpath, const char *output) { bool created = false; char dst[PATH_MAX] = {0}; u64 output_length = strlen(output); strncpy(dst, output, output_length); u64 ext_length = strlen(PAK_EXT); strncat(dst, PAK_EXT, ext_length); FILE *fp = fopen(dst, "wb"); if (!fp) { goto RETURN_CREATE_ASSET_PAK; } darr_t *toc_entries_darr = NULL; darr_t *pak_entries_darr = NULL; bool initialiased = darr_init(&toc_entries_darr) && darr_init(&pak_entries_darr); if (!initialiased) { goto FREE_ARRAYS_CREATE_ASSET_PAK; } pak_t pak = { .magic = PAK_MAGIC, .version = (pak_ver_t){ .major = PAK_MAJOR, .minor = PAK_MINOR, .patch = PAK_PATCH, }, .toc = (toc_t){ .count = 0, .size = 0, }, }; dirwalk_t *dw = NULL; dirwalk_result_t result = {0}; result = walk_dir(&dw, dirpath); if (!(result.fp)) { goto FREE_ARRAYS_CREATE_ASSET_PAK; } u64 offset = 0; while (result.reading) { if (result.fp) { ++(pak.toc.count); toc_entry_t *toc_entry = create_toc_entry(result.name, offset); pak_entry_t *pak_entry = create_pak_entry_from_file(result.fp); if (!toc_entry || !pak_entry) { goto FREE_ARRAYS_CREATE_ASSET_PAK; } pak.toc.size += sizeof(toc_entry_t) + toc_entry->length; offset += sizeof(pak_entry_t) + pak_entry->size; darr_add(&toc_entries_darr, (void *)toc_entry); darr_add(&pak_entries_darr, (void *)pak_entry); } result = walk_dir(&dw, NULL); } toc_entry_t **toc_entries = (toc_entry_t **)darr_get_items(toc_entries_darr); pak_entry_t **pak_entries = (pak_entry_t **)darr_get_items(pak_entries_darr); write_pak(&pak, toc_entries, pak_entries, fp); created = true; FREE_ARRAYS_CREATE_ASSET_PAK: darr_free(&pak_entries_darr); darr_free(&toc_entries_darr); fclose(fp); RETURN_CREATE_ASSET_PAK: return created; } pak_read_t *load_asset_pack(const char *filepath) { char full_path[PATH_MAX] = {0}; realpath(filepath, full_path); pak_read_t *pack = NULL; FILE *fp = fopen(full_path, "rb"); if (!fp) { goto RETURN_LOAD_ASSET_PACK; } pack = (pak_read_t *)malloc(sizeof(pak_read_t)); if (!pack) { goto CLOSE_FILE_LOAD_ASSET_PACK; } u64 file_size = get_file_length(fp); fread((void *)(&(pack->header)), sizeof(pak_t), 1, fp); u64 data_size = file_size - sizeof(pak_t); pack->buf = (u8 *)malloc(data_size); if (!(pack->buf)) { free(pack); pack = NULL; goto CLOSE_FILE_LOAD_ASSET_PACK; } fread((void *)(pack->buf), data_size, 1, fp); pack->toc = pack->buf; pack->assets_length = data_size - pack->header.toc.size; pack->assets = pack->buf + pack->header.toc.size; CLOSE_FILE_LOAD_ASSET_PACK: fclose(fp); RETURN_LOAD_ASSET_PACK: return pack; } // buf_t read_file_from_pack(pak_read_t *pack, const char *filename) {} void close_asset_pack(pak_read_t **pack) { if (!(*pack)) { return; } free(*pack); *pack = NULL; } toc_entry_t *create_toc_entry(const char *name, u64 offset) { u64 length = strlen(name); u64 size = sizeof(toc_entry_t) + length + 1; toc_entry_t *entry = (toc_entry_t *)malloc(size); if (!entry) { return NULL; } memset((void *)entry, 0, size); entry->offset = offset; entry->length = length + 1; strncpy(entry->name, name, length); return entry; } void write_toc_entry(toc_entry_t *entry, FILE *fp) { fwrite((void *)entry, sizeof(toc_entry_t) + entry->length, 1, fp); } void write_toc_entries(const toc_t *toc, toc_entry_t **entries, FILE *fp) { if (!fp || !entries) { return; } for (u64 i = 0; i < toc->count; ++i) { write_toc_entry(entries[i], fp); if (!entries[i]) { continue; } free(entries[i]); entries[i] = NULL; } } pak_entry_t *create_pak_entry(u64 data_length) { pak_entry_t *entry = (pak_entry_t *)malloc(sizeof(pak_entry_t) + data_length); if (!entry) { return NULL; } memset(entry, 0, data_length); entry->size = data_length; return entry; } pak_entry_t *create_pak_entry_from_file(FILE *fp) { pak_entry_t *entry = NULL; if (!fp) { goto RETURN_PAK_ENTRY; } u64 length = get_file_length(fp) + 1; entry = create_pak_entry(length); if (!entry) { goto RETURN_PAK_ENTRY; } read_entire_file((void *)(entry->data), fp); RETURN_PAK_ENTRY: return entry; } void write_pak_entry(const pak_entry_t *entry, FILE *fp) { fwrite((void *)entry, sizeof(pak_entry_t) + entry->size, 1, fp); } void write_pak(const pak_t *pak, toc_entry_t **toc_entries, pak_entry_t **pak_entries, FILE *fp) { fwrite(pak, sizeof(pak_t), 1, fp); write_toc_entries(&(pak->toc), toc_entries, fp); for (u64 i = 0; i < pak->toc.count; ++i) { write_pak_entry(pak_entries[i], fp); free(pak_entries[i]); } }