Mercurial > hg > dmlib
annotate dmres.c @ 26:2f463a59d732
Implement rudimentary resource system.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sat, 29 Sep 2012 05:29:38 +0300 |
parents | e0fc7863d024 |
children | 21c14afbf63d |
rev | line source |
---|---|
0 | 1 /* |
2 * dmlib | |
3 * -- Resource management | |
4 * Programmed and designed by Matti 'ccr' Hamalainen | |
5 * (C) Copyright 2003-2012 Tecnic Software productions (TNSP) | |
6 */ | |
7 #include "dmres.h" | |
8 #include <time.h> | |
9 | |
10 #if !defined(DMRES_PACKFS) && !defined(DMRES_STDIO) | |
11 #error At least one of DMRES_PACKFS, DMRES_STDIO must be defined. | |
12 #endif | |
13 | |
14 #define DMRES_LOCK(x) dmMutexLock(dfResourcesMutex) | |
15 #define DMRES_UNLOCK(x) dmMutexUnlock(dfResourcesMutex) | |
16 | |
17 | |
18 /* Global variables | |
19 */ | |
20 static BOOL dfResInitialized = FALSE; | |
21 static int dfResFlags = 0; | |
22 static char * dfResPath = NULL; | |
23 DMResource * dfResources = NULL; | |
24 DMMutex * dfResourcesMutex = NULL; | |
25 | |
26 | |
27 #ifdef DMRES_PACKFS | |
28 static DMPackFile *dfResPackFile = NULL; | |
29 static char * dfResPackFilename = NULL; | |
30 #endif | |
31 | |
32 | |
33 DMResource *dmres_new(const char *filename, int flags, size_t size) | |
34 { | |
35 DMResource *res = dmMalloc0(sizeof(DMResource)); | |
36 if (res == NULL) | |
37 return NULL; | |
38 | |
39 res->filename = dm_strdup(filename); | |
40 res->flags = flags; | |
41 res->dataSize = size; | |
42 | |
43 return res; | |
44 } | |
45 | |
46 | |
47 void dmres_free(DMResource *res) | |
48 { | |
49 if (res != NULL) | |
50 { | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
51 if (res->rdata != NULL && |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
52 res->rops != NULL && |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
53 res->rops->free != NULL) |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
54 { |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
55 res->rops->free(res); |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
56 res->rdata = NULL; |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
57 } |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
58 |
0 | 59 dmFree(res->filename); |
60 dmFree(res->data); | |
61 dmFree(res); | |
62 } | |
63 } | |
64 | |
65 | |
66 void dmres_insert(DMResource * node) | |
67 { | |
68 if (dfResources != NULL) | |
69 { | |
70 node->prev = dfResources->prev; | |
71 dfResources->prev->next = node; | |
72 dfResources->prev = node; | |
73 } | |
74 else | |
75 { | |
76 dfResources = node->prev = node; | |
77 } | |
78 | |
79 node->next = NULL; | |
80 } | |
81 | |
82 | |
83 void dmres_delete(DMResource * node) | |
84 { | |
85 if (node->prev) | |
86 node->prev->next = node->next; | |
87 | |
88 if (node->next) | |
89 node->next->prev = node->prev; | |
90 else | |
91 dfResources->prev = node->prev; | |
92 | |
93 node->prev = node->next = NULL; | |
94 } | |
95 | |
96 | |
97 DMResource * dmres_find(const char *filename) | |
98 { | |
99 DMResource *node, *found = NULL; | |
100 | |
101 DMRES_LOCK(); | |
102 | |
103 for (node = dfResources; node != NULL; node = node->next) | |
104 { | |
105 if (strcmp(node->filename, filename) == 0) | |
106 { | |
107 found = node; | |
108 break; | |
109 } | |
110 } | |
111 | |
112 DMRES_UNLOCK(); | |
113 | |
114 return found; | |
115 } | |
116 | |
117 | |
118 #ifdef DMRES_STDIO | |
119 /* Basic stdio file routines | |
120 */ | |
121 static int dm_stdio_fopen(DMResource *handle) | |
122 { | |
123 char *rfilename = dm_strdup_printf("%s%s", DMRES_DATA_PATH, handle->filename); | |
124 if (rfilename == NULL) | |
125 return DMERR_MALLOC; | |
126 | |
127 handle->fh = fopen(rfilename, "rb"); | |
128 dmFree(rfilename); | |
129 | |
130 handle->error = dmGetErrno(); | |
131 return (handle->fh != NULL) ? DMERR_OK : DMERR_FOPEN; | |
132 } | |
133 | |
134 | |
135 static void dm_stdio_fclose(DMResource * f) | |
136 { | |
137 if (f->fh != NULL) | |
138 { | |
139 fclose(f->fh); | |
140 f->fh = NULL; | |
141 } | |
142 } | |
143 | |
144 | |
145 static int dm_stdio_ferror(DMResource * f) | |
146 { | |
147 return f->error; | |
148 } | |
149 | |
150 | |
151 static int dm_stdio_fseek(DMResource *f, const off_t pos, const int whence) | |
152 { | |
153 int ret = fseek(f->fh, pos, whence); | |
154 f->error = dmGetErrno(); | |
155 return ret; | |
156 } | |
157 | |
158 | |
159 static off_t dm_stdio_fsize(DMResource *f) | |
160 { | |
161 off_t savePos, fileSize; | |
162 | |
163 // Check if the size is cached | |
164 if (f->dataSize != 0) | |
165 return f->dataSize; | |
166 | |
167 // Get file size | |
168 savePos = ftell(f->fh); | |
169 if (fseek(f->fh, 0L, SEEK_END) != 0) | |
170 { | |
171 f->error = dmGetErrno(); | |
172 return -1; | |
173 } | |
174 | |
175 fileSize = ftell(f->fh); | |
176 if (fseek(f->fh, savePos, SEEK_SET) != 0) | |
177 { | |
178 f->error = dmGetErrno(); | |
179 return -1; | |
180 } | |
181 | |
182 f->dataSize = fileSize; | |
183 return fileSize; | |
184 } | |
185 | |
186 | |
187 static off_t dm_stdio_ftell(DMResource * f) | |
188 { | |
189 return ftell(f->fh); | |
190 } | |
191 | |
192 | |
193 static BOOL dm_stdio_feof(DMResource * f) | |
194 { | |
195 return feof(f->fh); | |
196 } | |
197 | |
198 | |
199 static int dm_stdio_fgetc(DMResource * f) | |
200 { | |
201 int ret = fgetc(f->fh); | |
202 f->error = dmGetErrno(); | |
203 return ret; | |
204 } | |
205 | |
206 | |
207 static size_t dm_stdio_fread(void *ptr, size_t size, size_t nmemb, DMResource * f) | |
208 { | |
209 size_t ret = fread(ptr, size, nmemb, f->fh); | |
210 f->error = dmGetErrno(); | |
211 return ret; | |
212 } | |
213 | |
214 | |
215 static int dm_stdio_preload(DMResource *handle) | |
216 { | |
217 int ret = dm_stdio_fopen(handle); | |
218 if (ret != DMERR_OK) | |
219 return ret; | |
220 | |
221 dm_stdio_fsize(handle); | |
222 | |
223 handle->data = dmMalloc(handle->dataSize); | |
224 if (handle->data == NULL) | |
225 return DMERR_MALLOC; | |
226 | |
227 if (dm_stdio_fread(handle->data, sizeof(Uint8), handle->dataSize, handle) != handle->dataSize) | |
228 return DMERR_FREAD; | |
229 | |
230 return DMERR_OK; | |
231 } | |
232 | |
233 | |
234 DMResourceOps dfStdioFileOps = | |
235 { | |
236 dm_stdio_ferror, | |
237 dm_stdio_fseek, | |
238 dm_stdio_fsize, | |
239 dm_stdio_ftell, | |
240 dm_stdio_feof, | |
241 dm_stdio_fgetc, | |
242 dm_stdio_fread, | |
243 | |
244 dm_stdio_fopen, | |
245 dm_stdio_fclose, | |
246 dm_stdio_preload | |
247 }; | |
248 | |
249 DMResourceOps dfStdioFHOps = | |
250 { | |
251 dm_stdio_ferror, | |
252 dm_stdio_fseek, | |
253 dm_stdio_fsize, | |
254 dm_stdio_ftell, | |
255 dm_stdio_feof, | |
256 dm_stdio_fgetc, | |
257 dm_stdio_fread, | |
258 | |
259 NULL, | |
260 NULL, | |
261 NULL | |
262 }; | |
263 #endif | |
264 | |
265 | |
266 // Some mingw/windows headers define these as macros, which is bad for us | |
267 #ifdef __WIN32 | |
268 #undef ferror | |
269 #undef feof | |
270 #endif | |
271 | |
272 | |
273 /* | |
274 * PACK file routines | |
275 */ | |
276 #ifdef DMRES_PACKFS | |
277 static int dm_pack_preload(DMResource *handle) | |
278 { | |
279 DMPackEntry *node; | |
280 int res = DMERR_OK, cres, cdataLeft; | |
281 z_stream cstream; | |
282 Uint8 * cbuffer = NULL; | |
283 | |
284 // Search PACK nodelist for file | |
285 if ((node = dm_pack_find(dfResPackFile->entries, handle->filename)) == NULL) | |
286 { | |
287 dmError("Entry '%s' not found in PACK file.\n", handle->filename); | |
288 res = DMERR_NOT_FOUND; | |
289 goto error; | |
290 } | |
291 | |
292 // Seek to entry | |
293 if (fseek(dfResPackFile->file, node->offset, SEEK_SET) == -1) | |
294 { | |
295 dmError("Could not seek node position in PACK file.\n"); | |
296 res = DMERR_FSEEK; | |
297 goto error; | |
298 } | |
299 | |
300 // Allocate a structures and buffers | |
301 cbuffer = (Uint8 *) dmMalloc(DPACK_TMPSIZE); | |
302 if (cbuffer == NULL) | |
303 { | |
304 res = DMERR_MALLOC; | |
305 goto error; | |
306 } | |
307 | |
308 // Initialize fields | |
309 handle->dataOffset = 0; | |
310 handle->dataSize = node->size; | |
311 handle->data = (Uint8 *) dmMalloc(node->size); | |
312 if (handle->data == NULL) | |
313 { | |
314 res = DMERR_MALLOC; | |
315 goto error; | |
316 } | |
317 | |
318 // Initialize decompression | |
319 cstream.zalloc = (alloc_func) Z_NULL; | |
320 cstream.zfree = (free_func) Z_NULL; | |
321 cstream.opaque = (voidpf) Z_NULL; | |
322 cstream.next_out = handle->data; | |
323 cstream.avail_out = handle->dataSize; | |
324 cdataLeft = node->length; | |
325 cres = inflateInit(&(cstream)); | |
326 if (cres != Z_OK) | |
327 { | |
328 dmError("Could not initialize zlib stream inflation.\n"); | |
329 res = DMERR_INIT_FAIL; | |
330 goto error; | |
331 } | |
332 | |
333 // Uncompress the data | |
334 while (cdataLeft > 0 && | |
335 cstream.avail_out > 0 && cres == Z_OK) | |
336 { | |
337 cstream.avail_in = fread( | |
338 cbuffer, sizeof(Uint8), | |
339 (cdataLeft >= DPACK_TMPSIZE) ? DPACK_TMPSIZE : cdataLeft, | |
340 dfResPackFile->file); | |
341 | |
342 cdataLeft -= cstream.avail_in; | |
343 cstream.next_in = cbuffer; | |
344 cres = inflate(&cstream, Z_FULL_FLUSH); | |
345 } | |
346 | |
347 // Cleanup | |
348 inflateEnd(&(cstream)); | |
349 | |
350 error: | |
351 dmFree(cbuffer); | |
352 return res; | |
353 } | |
354 #endif | |
355 | |
356 | |
357 static void dm_mem_fclose(DMResource * f) | |
358 { | |
359 f->dataSize = 0; | |
360 f->dataOffset = 0; | |
361 dmFree(f->data); | |
362 f->data = NULL; | |
363 } | |
364 | |
365 | |
366 static int dm_mem_ferror(DMResource * f) | |
367 { | |
368 return f->error; | |
369 } | |
370 | |
371 | |
372 static int dm_mem_fseek(DMResource * f, const off_t offset, const int whence) | |
373 { | |
374 off_t newPos; | |
375 | |
376 // Calculate the new position | |
377 switch (whence) | |
378 { | |
379 case SEEK_SET: | |
380 newPos = offset; | |
381 break; | |
382 | |
383 case SEEK_CUR: | |
384 newPos = f->dataOffset + offset; | |
385 break; | |
386 | |
387 case SEEK_END: | |
388 newPos = f->dataSize + offset; | |
389 break; | |
390 | |
391 default: | |
392 return -1; | |
393 } | |
394 | |
395 // Set the new position | |
396 f->dataOffset = newPos; | |
397 | |
398 // Check the new position | |
399 if (newPos < 0 && (size_t) newPos >= f->dataSize) | |
400 return -1; | |
401 | |
402 return 0; | |
403 } | |
404 | |
405 | |
406 static off_t dm_mem_fsize(DMResource * f) | |
407 { | |
408 return f->dataSize; | |
409 } | |
410 | |
411 | |
412 static off_t dm_mem_ftell(DMResource * f) | |
413 { | |
414 return f->dataOffset; | |
415 } | |
416 | |
417 | |
418 static BOOL dm_mem_feof(DMResource * f) | |
419 { | |
420 // Check for EOF | |
421 if ((size_t) f->dataOffset <= f->dataSize) | |
422 return FALSE; | |
423 else | |
424 return TRUE; | |
425 } | |
426 | |
427 | |
428 static int dm_mem_fgetc(DMResource * f) | |
429 { | |
430 // Check for EOF | |
431 if ((size_t) f->dataOffset < f->dataSize) | |
432 return (int) f->data[f->dataOffset++]; | |
433 else | |
434 return EOF; | |
435 } | |
436 | |
437 | |
438 static size_t dm_mem_fread(void *buf, size_t size, size_t nmemb, DMResource * f) | |
439 { | |
440 size_t length = (size * nmemb); | |
441 | |
442 // Check if we can read the whole chunk | |
443 if (((size_t) f->dataOffset + length) >= f->dataSize) | |
444 { | |
445 nmemb = (f->dataSize - f->dataOffset) / size; | |
446 length = size * nmemb; | |
447 } | |
448 | |
449 memcpy(buf, f->data + f->dataOffset, length); | |
450 f->dataOffset += length; | |
451 return nmemb; | |
452 } | |
453 | |
454 | |
455 DMResourceOps dfPackFileOps = | |
456 { | |
457 dm_mem_ferror, | |
458 dm_mem_fseek, | |
459 dm_mem_fsize, | |
460 dm_mem_ftell, | |
461 dm_mem_feof, | |
462 dm_mem_fgetc, | |
463 dm_mem_fread, | |
464 | |
465 NULL, | |
466 dm_mem_fclose, | |
467 dm_pack_preload | |
468 }; | |
469 | |
470 | |
471 DMResourceOps dfMemIOFileOps = | |
472 { | |
473 dm_mem_ferror, | |
474 dm_mem_fseek, | |
475 dm_mem_fsize, | |
476 dm_mem_ftell, | |
477 dm_mem_feof, | |
478 dm_mem_fgetc, | |
479 dm_mem_fread, | |
480 | |
481 NULL, | |
482 NULL, | |
483 NULL | |
484 }; | |
485 | |
486 | |
487 /* FS file handling functions. These functions call the actual | |
488 * functions depending on where the file is located. | |
489 */ | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
490 static void dmf_init_fops(DMResource *handle) |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
491 { |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
492 // Check fops |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
493 if (handle->fops == NULL) |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
494 { |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
495 #ifdef DMRES_PACKFS |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
496 if (dfResFlags & DRF_USE_PACK) |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
497 handle->fops = &dfPackFileOps; |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
498 #ifdef DMRES_STDIO |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
499 else |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
500 handle->fops = &dfStdioFileOps; |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
501 #else |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
502 handle->fops = &dfPackFileOps; |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
503 #endif |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
504 |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
505 #else |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
506 handle->fops = &dfStdioFileOps; |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
507 #endif |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
508 } |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
509 } |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
510 |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
511 |
0 | 512 DMResource *dmf_open(const char *filename) |
513 { | |
514 int ret; | |
515 DMResource *handle; | |
516 | |
517 // Check master directory for resource | |
518 if ((handle = dmres_find(filename)) == NULL) | |
519 { | |
520 #ifdef DMRES_STDIO | |
521 // Hmm.. does not exist? Fall back to a stdio file | |
522 handle = dmres_new(filename, 0, 0); | |
523 if (handle == NULL) | |
524 return NULL; | |
525 | |
526 handle->fops = &dfStdioFileOps; | |
527 dmres_insert(handle); | |
528 #else | |
529 // Stdio not enabled, fail | |
530 return NULL; | |
531 #endif | |
532 } | |
533 | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
534 dmf_init_fops(handle); |
0 | 535 |
536 // Check if the data is preloaded | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
537 if (handle->flags & DMF_LOADED_RAW) |
0 | 538 { |
539 dmres_ref(handle); | |
540 return handle; | |
541 } | |
542 | |
543 // Check if we want to preload .. | |
544 ret = DMERR_INIT_FAIL; | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
545 if (((handle->flags & DMF_PRELOAD_RAW) || (dfResFlags & DRF_PRELOAD_ALL)) && |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
546 (handle->flags & DMF_LOADED_RAW) == 0 && |
0 | 547 handle->fops->preload != NULL) |
548 ret = handle->fops->preload(handle); | |
549 else | |
550 { | |
551 if (handle->fops->fopen != NULL) | |
552 ret = handle->fops->fopen(handle); | |
553 else | |
554 if (handle->fops->preload != NULL) | |
555 ret = handle->fops->preload(handle); | |
556 } | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
557 |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
558 if (((handle->flags & DMF_PRELOAD_RES) || (dfResFlags & DRF_PRELOAD_RES)) && |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
559 (handle->flags & DMF_LOADED_RES) == 0 && |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
560 handle->rops != NULL && |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
561 handle->rops->load != NULL) |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
562 ret = handle->rops->load(handle); |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
563 |
0 | 564 |
565 if (ret == DMERR_OK) | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
566 { |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
567 dmres_ref(handle); |
0 | 568 return handle; |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
569 } |
0 | 570 |
571 return NULL; | |
572 } | |
573 | |
574 | |
575 DMResource * dmf_open_memio(const char *filename, Uint8 *buf, size_t len) | |
576 { | |
577 DMResource *handle; | |
578 | |
579 // Check master directory for resource | |
580 if ((handle = dmres_find(filename)) == NULL) | |
581 { | |
582 // Hmm.. does not exist? Fall back to a stdio file | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
583 handle = dmres_new(filename, DMF_LOADED_RAW, len); |
0 | 584 if (handle == NULL) |
585 return NULL; | |
586 | |
587 handle->fops = &dfMemIOFileOps; | |
588 handle->data = buf; | |
589 dmres_insert(handle); | |
590 } | |
591 | |
592 // Increase refcount | |
593 dmres_ref(handle); | |
594 | |
595 return handle; | |
596 } | |
597 | |
598 | |
599 #ifdef DMRES_STDIO | |
600 DMResource * dmf_create_stdio(const char *filename) | |
601 { | |
602 DMResource *handle = dmres_new(filename, 0, 0); | |
603 if (handle == NULL) | |
604 return NULL; | |
605 | |
606 handle->fops = &dfStdioFileOps; | |
607 | |
608 handle->fh = fopen(filename, "rb"); | |
609 handle->error = dmGetErrno(); | |
610 | |
611 if (handle->fh != NULL) | |
612 { | |
613 dmres_ref(handle); | |
614 return handle; | |
615 } | |
616 else | |
617 { | |
618 dmres_free(handle); | |
619 return NULL; | |
620 } | |
621 } | |
622 | |
623 | |
624 DMResource * dmf_create_stdio_stream(FILE *fh) | |
625 { | |
626 DMResource *handle = dmres_new("", 0, 0); | |
627 if (handle == NULL) | |
628 return NULL; | |
629 | |
630 handle->fops = &dfStdioFHOps; | |
631 handle->fh = fh; | |
632 dmres_ref(handle); | |
633 return handle; | |
634 } | |
635 #endif | |
636 | |
637 | |
638 void dmf_close(DMResource * f) | |
639 { | |
640 if (f == NULL) | |
641 return; | |
642 | |
643 if (f->fops->fclose != NULL) | |
644 f->fops->fclose(f); | |
645 | |
646 dmres_unref(f); | |
647 } | |
648 | |
649 | |
650 int dmferror(DMResource * f) | |
651 { | |
652 f->atime = time(NULL); | |
653 return f->fops->ferror(f); | |
654 } | |
655 | |
656 int dmfseek(DMResource * f, off_t offset, int whence) | |
657 { | |
658 f->atime = time(NULL); | |
659 return f->fops->fseek(f, offset, whence); | |
660 } | |
661 | |
662 off_t dmfsize(DMResource * f) | |
663 { | |
664 f->atime = time(NULL); | |
665 return f->fops->fsize(f); | |
666 } | |
667 | |
668 off_t dmftell(DMResource * f) | |
669 { | |
670 f->atime = time(NULL); | |
671 return f->fops->ftell(f); | |
672 } | |
673 | |
674 BOOL dmfeof(DMResource * f) | |
675 { | |
676 f->atime = time(NULL); | |
677 return f->fops->feof(f); | |
678 } | |
679 | |
680 int dmfgetc(DMResource * f) | |
681 { | |
682 f->atime = time(NULL); | |
683 return f->fops->fgetc(f); | |
684 } | |
685 | |
686 size_t dmfread(void *ptr, size_t size, size_t nmemb, DMResource * f) | |
687 { | |
688 f->atime = time(NULL); | |
689 return f->fops->fread(ptr, size, nmemb, f); | |
690 } | |
691 | |
692 | |
693 int dmres_ref(DMResource *res) | |
694 { | |
695 DMRES_LOCK(); | |
696 res->atime = time(NULL); | |
697 res->refcount++; | |
698 DMRES_UNLOCK(); | |
699 | |
700 return res->refcount; | |
701 } | |
702 | |
703 | |
704 int dmres_unref(DMResource *res) | |
705 { | |
706 DMRES_LOCK(); | |
707 res->refcount--; | |
708 DMRES_UNLOCK(); | |
709 | |
710 return res->refcount; | |
711 } | |
712 | |
713 | |
714 int dmres_load_resfile(const char *filename) | |
715 { | |
716 int ret; | |
717 char line[256]; | |
718 FILE *f = fopen(filename, "r"); | |
719 if (f == NULL) | |
720 return DMERR_FOPEN; | |
721 | |
722 DMRES_LOCK(); | |
723 | |
724 while (fgets(line, sizeof(line) - 1, f) != NULL) | |
725 { | |
726 int fnstart, fsep; | |
727 for (fnstart = 0; isspace(line[fnstart]); fnstart++); | |
728 for (fsep = fnstart; line[fsep] && line[fsep] != '|'; fsep++); | |
729 if (line[fsep] == '|') | |
730 { | |
731 int flags, i; | |
732 for (i = fsep - 1; i > 0 && isspace(line[i]); i--) | |
733 line[i] = 0; | |
734 | |
735 for (i = fsep; isspace(line[i]); i++); | |
736 | |
737 if (sscanf(&line[i], "%x", &flags) == 1 && | |
738 strlen(&line[fnstart]) > 0) | |
739 { | |
740 | |
741 } | |
742 } | |
743 } | |
744 | |
745 DMRES_UNLOCK(); | |
746 fclose(f); | |
747 return ret; | |
748 } | |
749 | |
750 | |
751 int dmres_write_resfile(const char *filename) | |
752 { | |
753 int ret; | |
754 DMResource *node; | |
755 FILE *f = fopen(filename, "w"); | |
756 if (f == NULL) | |
757 return DMERR_FOPEN; | |
758 | |
759 DMRES_LOCK(); | |
760 | |
761 for (node = dfResources; node != NULL; node = node->next) | |
762 { | |
763 if (fprintf(f, "%s|%08x\n", node->filename, node->flags) < 0) | |
764 { | |
765 ret = DMERR_FWRITE; | |
766 goto error; | |
767 } | |
768 } | |
769 | |
770 error: | |
771 DMRES_UNLOCK(); | |
772 fclose(f); | |
773 return ret; | |
774 } | |
775 | |
776 | |
777 /* Resources subsystem initialization and shutdown routines | |
778 */ | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
779 int dmres_init(const char *filename, const char *path, int flags, int (*classifier)(DMResource *)) |
0 | 780 { |
781 // Check if we are already initialized | |
782 if (dfResInitialized) | |
783 return DMERR_ALREADY_INIT; | |
784 | |
785 dfResFlags = flags; | |
786 dfResPath = dm_strdup((path != NULL) ? path : DMRES_DATA_PATH); | |
787 dfResourcesMutex = dmCreateMutex(); | |
788 | |
789 if (flags & DRF_USE_PACK) | |
790 { | |
791 #ifdef DMRES_PACKFS | |
792 int ret; | |
793 DMPackEntry *node; | |
794 | |
795 dfResPackFilename = dm_strdup((filename != NULL) ? filename : DMRES_DATA_PACK); | |
796 | |
797 // Initialize PACK, open as read-only | |
798 ret = dm_pack_open(dfResPackFilename, &dfResPackFile, TRUE); | |
799 if (ret != DMERR_OK) | |
800 { | |
801 dmError("Error opening PACK file '%s', #%i: %s\n", | |
802 dfResPackFilename, ret, dmErrorStr(ret)); | |
803 | |
804 return DMERR_INIT_FAIL; | |
805 } | |
806 | |
807 // Initialize resources from a PACK file | |
808 for (node = dfResPackFile->entries; node != NULL; node = node->next) | |
809 { | |
4
e0fc7863d024
Mask out bits from resFlags that should not be there after initialization.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
810 DMResource *res = dmres_new(node->filename, node->resFlags & DMF_MASK, node->size); |
0 | 811 if (res == NULL) |
812 { | |
813 dmError("Could not allocate memory for resource node '%s' [0x%08x], %d.\n", | |
814 node->filename, node->resFlags, node->size); | |
815 return DMERR_INIT_FAIL; | |
816 } | |
817 | |
818 dmres_insert(res); | |
819 } | |
820 | |
821 #else | |
822 // PACK not compiled in, FAIL! | |
823 return DMERR_INIT_FAIL; | |
824 #endif | |
825 } | |
826 else | |
827 { | |
828 // Initialize resources from a resource directory | |
829 char *resFilename = dm_strdup_printf("%s%s", dfResPath, DMRES_RES_FILE); | |
830 int ret = dmres_load_resfile(resFilename); | |
831 dmFree(resFilename); | |
832 | |
833 if (ret != DMERR_OK) | |
834 return DMERR_INIT_FAIL; | |
835 } | |
836 | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
837 // Okay, classify resources |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
838 if (dfResources != NULL && classifier != NULL) |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
839 { |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
840 DMResource *node; |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
841 for (node = dfResources; node != NULL; node = node->next) |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
842 { |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
843 int ret = classifier(node); |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
844 if (ret != DMERR_OK) |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
845 return DMERR_INIT_FAIL; |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
846 } |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
847 } |
0 | 848 |
849 // Initialization complete | |
850 dfResInitialized = TRUE; | |
851 return DMERR_OK; | |
852 } | |
853 | |
854 | |
855 void dmres_close(void) | |
856 { | |
857 DMResource *node; | |
858 DMRES_LOCK(); | |
859 | |
860 if (!dfResInitialized) | |
861 return; | |
862 | |
863 // Shutdown possible subsystems | |
864 #ifdef DMRES_PACKFS | |
865 if (dfResFlags & DRF_USE_PACK) | |
866 { | |
867 int res = dm_pack_close(dfResPackFile); | |
868 if (res != DMERR_OK) | |
869 { | |
870 dmError("Error closing PACK, #%i: %s\n", | |
871 res, dmErrorStr(res)); | |
872 } | |
873 | |
874 dmFree(dfResPackFilename); | |
875 } | |
876 #endif | |
877 | |
878 // Free resource entries | |
879 node = dfResources; | |
880 while (node != NULL) | |
881 { | |
882 DMResource *next = node->next; | |
883 dmres_free(node); | |
884 node = next; | |
885 } | |
886 | |
887 // Etc. | |
888 dmFree(dfResPath); | |
889 DMRES_UNLOCK(); | |
890 dmDestroyMutex(dfResourcesMutex); | |
891 dfResInitialized = FALSE; | |
892 } | |
893 | |
894 | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
895 int dmres_preload(BOOL start, int *loaded, int *total) |
0 | 896 { |
897 static DMResource *dfPreload = NULL; | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
898 int ret = DMERR_OK; |
0 | 899 |
900 DMRES_LOCK(); | |
901 | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
902 // Initialize preloading |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
903 if (dfPreload == NULL || start) |
0 | 904 { |
905 DMResource *node; | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
906 |
0 | 907 dfPreload = dfResources; |
908 *loaded = 0; | |
909 *total = 0; | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
910 |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
911 // Calculate total number of resources to be preloaded |
0 | 912 for (node = dfResources; node != NULL; node = node->next) |
913 { | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
914 if ((dfResFlags & (DRF_PRELOAD_ALL | DRF_PRELOAD_RES)) || |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
915 (node->flags & (DMF_PRELOAD_RAW | DMF_PRELOAD_RES))) |
0 | 916 (*total)++; |
917 } | |
918 } | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
919 else |
0 | 920 if (dfPreload != NULL) |
921 { | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
922 // Check if the raw resource wants to be preloaded |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
923 if (((dfPreload->flags & DMF_PRELOAD_RAW) || (dfResFlags & DRF_PRELOAD_ALL)) && |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
924 (dfPreload->flags & DMF_LOADED_RAW) == 0) |
0 | 925 { |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
926 dmf_init_fops(dfPreload); |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
927 if (dfPreload->fops->preload != NULL) |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
928 { |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
929 ret = dfPreload->fops->preload(dfPreload); |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
930 if (ret == DMERR_OK) |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
931 { |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
932 dfPreload->flags |= DMF_LOADED_RAW; |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
933 (*loaded)++; |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
934 } |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
935 else |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
936 goto error; |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
937 } |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
938 } |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
939 |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
940 // Preload actual resource, if requested |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
941 if (((dfPreload->flags & DMF_PRELOAD_RES) || (dfResFlags & DRF_PRELOAD_RES)) && |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
942 (dfPreload->flags & DMF_LOADED_RES) == 0 && |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
943 dfPreload->rops != NULL && |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
944 dfPreload->rops->load != NULL) |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
945 { |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
946 dmf_init_fops(dfPreload); |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
947 ret = dfPreload->rops->load(dfPreload); |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
948 if (ret != DMERR_OK) |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
949 goto error; |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
950 |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
951 dfPreload->flags |= DMF_LOADED_RES; |
0 | 952 } |
953 | |
954 dfPreload = dfPreload->next; | |
955 } | |
956 | |
957 DMRES_UNLOCK(); | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
958 return (dfPreload == NULL) ? DMERR_OK : DMERR_PROGRESS; |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
959 |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
960 error: |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
961 DMRES_UNLOCK(); |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
962 return ret; |
0 | 963 } |
964 | |
965 | |
966 void dmres_prune(int agems, int flags) | |
967 { | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
968 DMResource *node; |
0 | 969 int currtime = time(NULL); |
970 DMRES_LOCK(); | |
971 | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
972 for (node = dfResources; node != NULL; node = node->next) |
0 | 973 { |
974 // Check if node has refcount of 0 and is | |
975 // not marked as persistent resource | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
976 if (node->refcount == 0 && |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
977 (node->flags & DMF_PERSIST) == 0 && |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
978 (node->flags & (DMF_LOADED_RES | DMF_LOADED_RAW))) |
0 | 979 { |
980 // Check if we match either one of atime or mtime | |
981 if (((flags & DMPRUNE_ATIME) && | |
982 currtime - node->atime >= agems) || | |
983 ((flags & DMPRUNE_MTIME) && | |
984 currtime - node->mtime >= agems)) | |
985 { | |
26
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
986 // Check if resource data is loaded |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
987 if (node->rdata != NULL && |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
988 node->rops != NULL && |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
989 node->rops->free != NULL) |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
990 { |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
991 node->rops->free(node); |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
992 node->flags &= !DMF_LOADED_RES; |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
993 } |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
994 |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
995 // Check if raw data is loaded |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
996 if (node->flags & DMF_LOADED_RAW) |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
997 { |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
998 dmFree(node->data); |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
999 node->data = NULL; |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
1000 node->flags &= !DMF_LOADED_RAW; |
2f463a59d732
Implement rudimentary resource system.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
1001 } |
0 | 1002 } |
1003 } | |
1004 } | |
1005 | |
1006 DMRES_UNLOCK(); | |
1007 } | |
1008 | |
1009 | |
1010 /* Helper resource access routines | |
1011 */ | |
1012 int dmf_read_str(DMResource *f, Uint8 *s, size_t l) | |
1013 { | |
1014 return dmfread(s, sizeof(Uint8), l, f) == l; | |
1015 } | |
1016 | |
1017 | |
1018 #define DM_DEFINE_FUNC(xname, xtype, xmacro) \ | |
1019 BOOL dmf_read_ ## xname (DMResource *f, xtype *v) { \ | |
1020 xtype result; \ | |
1021 if (dmfread(&result, sizeof( xtype ), 1, f) != 1) \ | |
1022 return FALSE; \ | |
1023 *v = DM_ ## xmacro ## _TO_NATIVE (result); \ | |
1024 return TRUE; \ | |
1025 } | |
1026 | |
1027 DM_DEFINE_FUNC(le16, Uint16, LE16) | |
1028 DM_DEFINE_FUNC(le32, Uint32, LE32) | |
1029 | |
1030 DM_DEFINE_FUNC(be16, Uint16, BE16) | |
1031 DM_DEFINE_FUNC(be32, Uint32, BE32) | |
1032 | |
1033 #ifdef DM_HAVE_64BIT | |
1034 DM_DEFINE_FUNC(le64, Uint64, LE64) | |
1035 DM_DEFINE_FUNC(be64, Uint64, BE64) | |
1036 #endif |