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