summaryrefslogtreecommitdiff
path: root/asset.c
blob: 0eca4043e2722ca8b691630ebd672ff8d640b1a8 (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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "asset.h"
#include "memory.h"
#include "plat.h"
#include "standard.h"
#include <stdlib.h>

static const Asset_Meta asset_meta[] = {
#define x(id, type, path) { type, path },
	assets_xmacro()
#undef x
};

Asset* loaded_assets[asset_id_count];

static void init_mesh_asset(Asset* asset, void* raw, int size) {
	Mesh* m = raw;
	asset->payload = raw;
	asset->payload_size = size;
	m->p = (int*)&m[1];
	m->n = (int*)&m->p[m->pc * 3];
	m->t = (int*)&m->n[m->nc * 3];
	m->verts = (Mesh_Vert*)&m->t[m->tc * 2];
}

/* Loading assets isn't that efficient. Too bad. */
static int get_asset_info(
	File* pack,
	int pack_count,
	const char* name,
	int* offset,
	int* size
) {
	int head_size = 8, i;
	char buf[56];
	file_seek(pack, head_size, file_whence_begin);
	for (i = 0; i < pack_count; i++) {
		file_read(pack, size,   4);
		file_read(pack, offset, 4);
		file_read(pack, buf,    sizeof buf);
		if (string_equal(buf, name)) {
			return 1;
		}
	}
	return 0;
}

Asset_Data* read_asset_data(
	const char* name,
	Arena* arena
) {
	Asset_Data* r = 0;
	File* pack;
	int pack_count, offset, size;
	pack = file_open("pack", file_flags_read);
	if (!pack) {
		print_err("Couldn't find 'pack'. Did you delete it?\n");
		pbreak(error_file_not_found);
		return 0;
	}
	file_read(pack, &pack_count, 4);
	if (get_asset_info(pack, pack_count, name, &offset, &size)) {
		r = arena_alloc(arena, sizeof *r);
		r->offset = offset;
		r->size = size;
		r->buffer = arena_alloc(arena, r->size);
		file_seek(pack, offset, file_whence_begin);
		file_read(pack, r->buffer, r->size);
	} else {
		print_err(\
			"%s doesn't exist in the pack. "
			"Is the pack corrupt?\n",
			name
		);
		file_close(pack);
		return 0;
	}
	file_close(pack);
	return r;
}

void preload_assets(Arena* mem) {
	int offset, size, pack_count, id;
	Asset* asset;
	File* pack;
	const Asset_Meta* meta;
	const char* name;
	Asset_Type type;
	void* raw;
	pack = file_open("pack", file_flags_read);
	if (!pack) {
		print_err("Couldn't find 'pack'. Did you delete it?\n");
		pbreak(error_file_not_found);
	}
	file_read(pack, &pack_count, 4);
#define gi(e_) \
		meta = get_asset_meta((Asset_ID)id); \
		name = meta->name; \
		type = meta->type; \
		if (get_asset_info( \
			pack, \
			pack_count, \
			name, \
			&offset, \
			&size \
		)) { \
			file_seek(pack, offset, file_whence_begin); \
			e_ \
		} else { \
			print_err( \
				"%s doesn't exist in the pack. " \
				"Is the pack corrupt?\n", \
				name \
			); \
			pbreak(error_file_not_found); \
		}
	for (id = 0; id < asset_id_count; id++) {
		gi({
			asset = arena_alloc(mem, sizeof *asset);
			asset->id = (Asset_ID)id;
			asset->type = type;
			raw = arena_alloc(mem, size);
			file_seek(pack, offset, file_whence_begin);
			file_read(pack, raw, size);
			switch (type) {
				case asset_type_mesh:
					init_mesh_asset(asset, raw, size);
					break;
				default:
					print_err("Invalid asset type.\n");
					pbreak(error_invalid_asset);
					break;
			}
			loaded_assets[id] = asset;
		});
	}
#undef gi
	file_close(pack);
}

const Asset* get_asset(Asset_ID id) {
	return loaded_assets[id];
}

const Asset_Meta* get_asset_meta(Asset_ID id) {
	return &asset_meta[id];
}

const struct Mesh* get_mesh(Asset_ID id) {
	const Asset* a = get_asset(id);
	return (struct Mesh*)a->payload;
}