diff options
| author | quou <quou@disroot.org> | 2024-12-22 22:19:36 +1100 | 
|---|---|---|
| committer | quou <quou@disroot.org> | 2024-12-22 22:19:36 +1100 | 
| commit | 58245585cbe77e6c03ebe13f29e10393ff3c45b4 (patch) | |
| tree | 6c3dcd8e9adcbc699318d4062bb2cf594116702e /qstd | |
| parent | 82767020e84ec8c1af2e3817fc7efede5497c82d (diff) | |
cute asset loading system
Diffstat (limited to 'qstd')
| -rw-r--r-- | qstd/Makefile | 7 | ||||
| -rw-r--r-- | qstd/pack.c | 165 | ||||
| -rw-r--r-- | qstd/pack.h | 40 | 
3 files changed, 210 insertions, 2 deletions
| diff --git a/qstd/Makefile b/qstd/Makefile index 3c4b6a8..c4b088b 100644 --- a/qstd/Makefile +++ b/qstd/Makefile @@ -5,7 +5,7 @@ defines = -Dplat_x86 -Dplat_posix -Dallocation_default_alignment=8  cflags = -std=c90 -pedantic -Wall -Wextra $(DEBUG_COMPILE_FLAG) $(includes) $(defines)  lflags = $(DEBUG_LINK_FLAG) -objects = plat.o memory.o str.o +objects = plat.o memory.o str.o pack.o  .PHONY: all clean @@ -17,9 +17,12 @@ memory.o: memory.c memory.h plat.h  plat.o: plat.c plat.h  	$(CC) -c $(cflags) plat.c -o plat.o -str.o: str.c str.h +str.o: str.c str.h memory.h  	$(CC) -c $(cflags) str.c -o str.o +pack.o: pack.c pack.h str.h plat.h memory.h +	$(CC) -c $(cflags) pack.c -o pack.o +  $(target): $(objects)  	$(AR) -rcs $(target) $(objects) diff --git a/qstd/pack.c b/qstd/pack.c new file mode 100644 index 0000000..e9ca0c3 --- /dev/null +++ b/qstd/pack.c @@ -0,0 +1,165 @@ +#include "memory.h" +#include "pack.h" +#include "plat.h" +#include "str.h" + +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> + +#define pack_max_files 4 + +typedef struct Pack_File { +	FILE* handle; +	Pack_Entry* entry; +	int offset; +} Pack_File; + +Pack_Entry* get_pack_table(Pack* p) { +	return (Pack_Entry*)( +		(char*)&p[1] + pack_max_files * sizeof(Pack_File) +	); +} + +int get_pack_size(int entry_count) { +	return sizeof(Pack) + +		pack_max_files * sizeof(Pack_File) + +		entry_count * sizeof(Pack_Entry); +} + +Pack_Entry* pack_find_entry(Pack* p, const char* name) { +	Pack_Entry* tab = get_pack_table(p); +	uint32_t hash = hash_string(name); +	int idx = (int)(hash % p->file_count), i; +	int e = (int)p->file_count; +	for (i = 0; i < e; i++) { +		Pack_Entry* e = &tab[idx]; +		if (!e->name[0] || string_equal(name, e->name)) +			return e; +		idx = (int)((idx + 1) % p->file_count); +	} +	return 0; +} + +static void insert_entry(Pack* p, const Pack_Entry* e) { +	Pack_Entry* d = pack_find_entry(p, e->name); +	assert(d != 0); +	if (d->name[0]) +		print_war("Duplicate entry in %s: %s\n", p->filename, e->name); +	*d = *e; +} + +static void read_table(Pack* p, FILE* f) { +	uint32_t i, e = p->file_count; +	Pack_Entry* tab = get_pack_table(p); +	for (i = 0; i < e; i++) +		tab[i].name[0] = 0; +	for (i = 0; i < e; i++) { +		Pack_Entry e; +		fread(&e, sizeof e, 1, f); +		insert_entry(p, &e); +	} +} + +static void init_files(Pack* p) { +	int i; +	Pack_File* files = (Pack_File*)&p[1]; +	for (i = 0; i < pack_max_files; i++) { +		files[i].handle = 0; +	} +} + +Pack* pack_open(const char* filename, Arena* a) { +	Pack* p; +	char magic[4]; +	uint32_t entry_count; +	FILE* f = fopen(filename, "rb"); +	if (!f) return 0; +	fread(magic, 1, 4, f); +	if ( +		magic[0] != 'P' || +		magic[1] != 'A' || +		magic[2] != 'C' || +		magic[3] != 'K' +	) { +		fclose(f); +		return 0; +	} +	fread(&entry_count, 4, 1, f); +	p = arena_alloc(a, get_pack_size(entry_count)); +	p->filename = dup_string(a, filename); +	p->file_count = entry_count; +	init_files(p); +	read_table(p, f); +	fclose(f); +	return p; +} + +void pack_close(Pack* p) { +	(void)p; +} + +Pack_Entry* pack_get_entry(Pack* p, const char* name) { +	Pack_Entry* e = pack_find_entry(p, name); +	if (!e || e->name[0] == 0) return 0; +	return e; +} + +static Pack_File* init_handle( +	Pack* p, +	Pack_File* h, +	const char* name +) { +	FILE* f; +	Pack_Entry* e = pack_find_entry(p, name); +	if (!e || !e->name[0]) return 0; +	f = fopen(p->filename, "rb"); +	if (!f) return 0; +	h->offset = 0; +	h->handle = f; +	h->entry = e; +	return h; +} + +Pack_File* pack_open_file(Pack* p, const char* name) { +	int i; +	Pack_File* files = (Pack_File*)&p[1]; +	for (i = 0; i < pack_max_files; i++) { +		Pack_File* file = &files[i]; +		if (!file->handle) +			return init_handle(p, file, name); +	} +	return 0; +} + +void pack_close_file(Pack_File* f) { +	fclose(f->handle); +} + +int pack_read(Pack_File* f, void* buf, int size) { +	int diff = (f->offset + size) - f->entry->size; +	int read; +	if (diff > 0) size -= diff; +	fseek(f->handle, f->entry->offset + f->offset, SEEK_SET); +	read = fread(buf, 1, size, f->handle); +	f->offset += read; +	return read; +} + +void pack_seek(Pack_File* f, int offset, Seek_Rel rel) { +	switch (rel) { +		case seek_rel_cur: +			f->offset += offset; +			break; +		case seek_rel_start: +			f->offset = offset; +			break; +		case seek_rel_end: +			f->offset = f->entry->size - offset; +			break; +	} +} + +int pack_tell(Pack_File* f) { +	return f->offset; +} diff --git a/qstd/pack.h b/qstd/pack.h new file mode 100644 index 0000000..447cd5b --- /dev/null +++ b/qstd/pack.h @@ -0,0 +1,40 @@ +#ifndef pack_h +#define pack_h + +#include <stdint.h> + +struct Arena; +struct Pack_File; + +typedef struct { +	char name[56]; +	uint32_t offset; +	uint32_t size; +} Pack_Entry; + +typedef struct Pack { +	char* filename; +	uint32_t file_count; +} Pack; + +Pack_Entry* pack_find_entry(Pack* p, const char* name); +Pack_Entry* get_pack_table(Pack* p); +int get_pack_size(int entry_count); + +Pack* pack_open(const char* filename, struct Arena* a); +void pack_close(Pack* p); +Pack_Entry* pack_get_entry(Pack* p, const char* name); + +typedef enum { +	seek_rel_cur, +	seek_rel_start, +	seek_rel_end +} Seek_Rel; + +struct Pack_File* pack_open_file(Pack* p, const char* name); +void pack_close_file(struct Pack_File* h); +int pack_read(struct Pack_File* f, void* buf, int size); +void pack_seek(struct Pack_File* f, int offset, Seek_Rel rel); +int pack_tell(struct Pack_File* f); + +#endif |