summaryrefslogtreecommitdiff
path: root/asset.cpp
blob: 09260e0ee1220c00303006cf7cee98fab7018956 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "asset.hpp"

extern "C" {
#include "memory.h"
#include "pack.h"
#include "plat.h"
#include "str.h"
}

#define max_asset_types 32

struct RLoader {
	char magic[4];
	Asset_Loader* loader;
};

struct Manager {
	RLoader loaders[max_asset_types];

	Manager() {
		int i;
		for (i = 0; i < max_asset_types; i++) {
			loaders[i].loader = 0;
		}
	}

	RLoader* find_loader(const char* magic) {
		uint32_t hash = hash_string(magic);
		int bucket = (int)(hash % max_asset_types);
		int i;
		for (i = 0; i < max_asset_types; i++) {
			RLoader& e = loaders[bucket];
			if (!e.loader || (
				e.magic[0] == magic[0] &&
				e.magic[1] == magic[1] &&
				e.magic[2] == magic[2] &&
				e.magic[3] == magic[3]
			)) return &e;
			bucket = (bucket + 1) % max_asset_types;
		}
		return 0;
	}

	Asset_Loader& get_loader(const char* magic) {
		RLoader* r = find_loader(magic);
		assert(r != 0 && r->loader != 0);
		return *r->loader;
	}

	void set_loader(const char* magic, Asset_Loader* l) {
		RLoader* r = find_loader(magic);
		assert(r != 0 && r->loader == 0);
		r->magic[0] = magic[0];
		r->magic[1] = magic[1];
		r->magic[2] = magic[2];
		r->magic[3] = magic[3];
		r->loader = l;
	}
} manager;

void register_asset_loader(
	const char* magic,
	Asset_Loader* loader
) {
	manager.set_loader(magic, loader);
}

void Asset_Arena::init(Arena* arena, const char* pack_name) {
	p = pack_open(pack_name, arena);
	a = arena;
	assets = 0;
}

void Asset_Arena::destroy() {
	Asset* a;
	for (a = assets; a; a = a->next) {
		a->unload(a->loader);
	}
	pack_close(p);
}

void Asset_Arena::claim(Asset* a) {
	if (assets) {
		a->next = assets;
		assets = a;
	} else assets = a;
}

Asset* Asset_Arena::load(const char* name) {
	char magic[4];
	Pack_File* f = pack_open_file(p, name);
	if (!f) return 0;
	pack_read(f, magic, 4);
	pack_seek(f, 0, seek_rel_start);
	Asset_Loader& loader = manager.get_loader(magic);
	Asset* asset = loader.load(a, f);
	asset->loader = &loader;
	pack_close_file(f);
	claim(asset);
	return asset;
}