1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Datafile reading routines.
12 *
13 * By Shawn Hargreaves.
14 *
15 * Elias Pschernig made load_datafile_object() handle properties.
16 *
17 * See readme.txt for copyright information.
18 */
19
20
21 #include <string.h>
22
23 #include "allegro.h"
24 #include "allegro/internal/aintern.h"
25
26
27
28 static void unload_midi(MIDI *m);
29 static void initialise_datafile(DATAFILE *data);
30
31
32
33 /* hack to let the grabber prevent compiled sprites from being compiled */
34 int _compile_sprites = TRUE;
35
36 /* flag to detect whether compiled datafiles are constructed:
37 * A runtime flag is required because the shared version of the library may
38 * have to deal both with executables that use constructors and with
39 * executables that don't.
40 */
41 static int constructed_datafiles = FALSE;
42
43 static void (*datafile_callback)(DATAFILE *) = NULL;
44
45
46
47 /* load_st_data:
48 * I'm not using this format any more, but files created with the old
49 * version of Allegro might have some bitmaps stored like this. It is
50 * the 4bpp planar system used by the Atari ST low resolution mode.
51 */
load_st_data(unsigned char * pos,long size,PACKFILE * f)52 static void load_st_data(unsigned char *pos, long size, PACKFILE *f)
53 {
54 int c;
55 unsigned int d1, d2, d3, d4;
56
57 size /= 8; /* number of 4 word planes to read */
58
59 while (size) {
60 d1 = pack_mgetw(f);
61 d2 = pack_mgetw(f);
62 d3 = pack_mgetw(f);
63 d4 = pack_mgetw(f);
64 for (c=0; c<16; c++) {
65 *(pos++) = ((d1 & 0x8000) >> 15) + ((d2 & 0x8000) >> 14) +
66 ((d3 & 0x8000) >> 13) + ((d4 & 0x8000) >> 12);
67 d1 <<= 1;
68 d2 <<= 1;
69 d3 <<= 1;
70 d4 <<= 1;
71 }
72 size--;
73 }
74 }
75
76
77
78 /* read_block:
79 * Reads a block of size bytes from a file, allocating memory to store it.
80 */
read_block(PACKFILE * f,int size,int alloc_size)81 static void *read_block(PACKFILE *f, int size, int alloc_size)
82 {
83 void *p;
84
85 p = _AL_MALLOC_ATOMIC(MAX(size, alloc_size));
86 if (!p) {
87 *allegro_errno = ENOMEM;
88 return NULL;
89 }
90
91 pack_fread(p, size, f);
92
93 if (pack_ferror(f)) {
94 _AL_FREE(p);
95 return NULL;
96 }
97
98 return p;
99 }
100
101
102
103 /* read_bitmap:
104 * Reads a bitmap from a file, allocating memory to store it.
105 */
read_bitmap(PACKFILE * f,int bits,int allowconv)106 static BITMAP *read_bitmap(PACKFILE *f, int bits, int allowconv)
107 {
108 int x, y, w, h, c, r, g, b, a;
109 int destbits, rgba;
110 unsigned short *p16;
111 uint32_t *p32;
112 BITMAP *bmp;
113
114 if (bits < 0) {
115 bits = -bits;
116 rgba = TRUE;
117 }
118 else
119 rgba = FALSE;
120
121 if (allowconv)
122 destbits = _color_load_depth(bits, rgba);
123 else
124 destbits = 8;
125
126 w = pack_mgetw(f);
127 h = pack_mgetw(f);
128
129 bmp = create_bitmap_ex(MAX(bits, 8), w, h);
130 if (!bmp) {
131 *allegro_errno = ENOMEM;
132 return NULL;
133 }
134
135 switch (bits) {
136
137 case 4:
138 /* old format ST data */
139 load_st_data(bmp->dat, w*h/2, f);
140 break;
141
142 case 8:
143 /* 256 color bitmap */
144 pack_fread(bmp->dat, w*h, f);
145
146 break;
147
148 case 15:
149 /* 15bit hicolor */
150 for (y=0; y<h; y++) {
151 p16 = (uint16_t *)bmp->line[y];
152
153 for (x=0; x<w; x++) {
154 c = pack_igetw(f);
155 r = _rgb_scale_5[(c >> 11) & 0x1F]; /* stored as 16 bit */
156 g = _rgb_scale_6[(c >> 5) & 0x3F];
157 b = _rgb_scale_5[c & 0x1F];
158 p16[x] = makecol15(r, g, b);
159 }
160 }
161 break;
162
163 case 16:
164 /* 16bit hicolor */
165 for (y=0; y<h; y++) {
166 p16 = (uint16_t *)bmp->line[y];
167
168 for (x=0; x<w; x++) {
169 c = pack_igetw(f);
170 r = _rgb_scale_5[(c >> 11) & 0x1F];
171 g = _rgb_scale_6[(c >> 5) & 0x3F];
172 b = _rgb_scale_5[c & 0x1F];
173 p16[x] = makecol16(r, g, b);
174 }
175 }
176 break;
177
178 case 24:
179 /* 24bit truecolor */
180 for (y=0; y<h; y++) {
181 for (x=0; x<w; x++) {
182 r = pack_getc(f);
183 g = pack_getc(f);
184 b = pack_getc(f);
185
186 if (rgba)
187 pack_getc(f);
188
189 c = makecol24(r, g, b);
190 WRITE3BYTES(bmp->line[y] + (x * 3), c);
191 }
192 }
193 break;
194
195 case 32:
196 /* 32bit rgba */
197 for (y=0; y<h; y++) {
198 p32 = (uint32_t *)bmp->line[y];
199
200 for (x=0; x<w; x++) {
201 r = pack_getc(f);
202 g = pack_getc(f);
203 b = pack_getc(f);
204
205 if (rgba)
206 a = pack_getc(f);
207 else
208 a = 0;
209
210 p32[x] = makeacol32(r, g, b, a);
211 }
212 }
213 break;
214
215 }
216
217 if (bits != destbits) {
218 BITMAP *tmp = bmp;
219 bmp = create_bitmap_ex(destbits, w, h);
220 if (!bmp) {
221 *allegro_errno = ENOMEM;
222 return NULL;
223 }
224 blit(tmp, bmp, 0, 0, 0, 0, bmp->w, bmp->h);
225 destroy_bitmap(tmp);
226 }
227
228 return bmp;
229 }
230
231
232
233 /* read_font_fixed:
234 * Reads a fixed pitch font from a file. This format is no longer used.
235 */
read_font_fixed(PACKFILE * pack,int height,int maxchars)236 static FONT *read_font_fixed(PACKFILE *pack, int height, int maxchars)
237 {
238 FONT *f = NULL;
239 FONT_MONO_DATA *mf = NULL;
240 FONT_GLYPH **gl = NULL;
241
242 int i = 0;
243
244 f = _AL_MALLOC(sizeof(FONT));
245 mf = _AL_MALLOC(sizeof(FONT_MONO_DATA));
246 gl = _AL_MALLOC(sizeof(FONT_GLYPH *) * maxchars);
247
248 if (!f || !mf || !gl) {
249 _AL_FREE(f);
250 _AL_FREE(mf);
251 _AL_FREE(gl);
252 *allegro_errno = ENOMEM;
253 return NULL;
254 }
255
256 f->data = mf;
257 f->height = height;
258 f->vtable = font_vtable_mono;
259
260 mf->begin = ' ';
261 mf->end = ' ' + maxchars;
262 mf->next = NULL;
263 mf->glyphs = gl;
264
265 memset(gl, 0, sizeof(FONT_GLYPH *) * maxchars);
266
267 for (i = 0; i < maxchars; i++) {
268 FONT_GLYPH *g = _AL_MALLOC(sizeof(FONT_GLYPH) + height);
269
270 if (!g) {
271 destroy_font(f);
272 *allegro_errno = ENOMEM;
273 return NULL;
274 }
275
276 gl[i] = g;
277 g->w = 8;
278 g->h = height;
279
280 pack_fread(g->dat, height, pack);
281 }
282
283 return f;
284 }
285
286
287
288 /* read_font_prop:
289 * Reads a proportional font from a file. This format is no longer used.
290 */
read_font_prop(PACKFILE * pack,int maxchars)291 static FONT *read_font_prop(PACKFILE *pack, int maxchars)
292 {
293 FONT *f = NULL;
294 FONT_COLOR_DATA *cf = NULL;
295 BITMAP **bits = NULL;
296 int i = 0, h = 0;
297
298 f = _AL_MALLOC(sizeof(FONT));
299 cf = _AL_MALLOC(sizeof(FONT_COLOR_DATA));
300 bits = _AL_MALLOC(sizeof(BITMAP *) * maxchars);
301
302 if (!f || !cf || !bits) {
303 _AL_FREE(f);
304 _AL_FREE(cf);
305 _AL_FREE(bits);
306 *allegro_errno = ENOMEM;
307 return NULL;
308 }
309
310 f->data = cf;
311 f->vtable = font_vtable_color;
312
313 cf->begin = ' ';
314 cf->end = ' ' + maxchars;
315 cf->next = NULL;
316 cf->bitmaps = bits;
317
318 memset(bits, 0, sizeof(BITMAP *) * maxchars);
319
320 for (i = 0; i < maxchars; i++) {
321 if (pack_feof(pack)) break;
322
323 bits[i] = read_bitmap(pack, 8, FALSE);
324 if (!bits[i]) {
325 destroy_font(f);
326 return NULL;
327 }
328
329 if (bits[i]->h > h) h = bits[i]->h;
330 }
331
332 while (i < maxchars) {
333 bits[i] = create_bitmap_ex(8, 8, h);
334 if (!bits[i]) {
335 destroy_font(f);
336 *allegro_errno = ENOMEM;
337 return NULL;
338 }
339
340 clear_bitmap(bits[i]);
341 i++;
342 }
343
344 f->height = h;
345
346 return f;
347 }
348
349
350
351 /* read_font_mono:
352 * Helper for read_font, below
353 */
read_font_mono(PACKFILE * f,int * hmax)354 static FONT_MONO_DATA *read_font_mono(PACKFILE *f, int *hmax)
355 {
356 FONT_MONO_DATA *mf = NULL;
357 int max = 0, i = 0;
358 FONT_GLYPH **gl = NULL;
359
360 mf = _AL_MALLOC(sizeof(FONT_MONO_DATA));
361 if (!mf) {
362 *allegro_errno = ENOMEM;
363 return NULL;
364 }
365
366 mf->begin = pack_mgetl(f);
367 mf->end = pack_mgetl(f) + 1;
368 mf->next = NULL;
369 max = mf->end - mf->begin;
370
371 mf->glyphs = gl = _AL_MALLOC(sizeof(FONT_GLYPH *) * max);
372 if (!gl) {
373 _AL_FREE(mf);
374 *allegro_errno = ENOMEM;
375 return NULL;
376 }
377
378 for (i = 0; i < max; i++) {
379 int w, h, sz;
380
381 w = pack_mgetw(f);
382 h = pack_mgetw(f);
383 sz = ((w + 7) / 8) * h;
384
385 if (h > *hmax) *hmax = h;
386
387 gl[i] = _AL_MALLOC(sizeof(FONT_GLYPH) + sz);
388 if (!gl[i]) {
389 while (i) {
390 i--;
391 _AL_FREE(mf->glyphs[i]);
392 }
393 _AL_FREE(mf);
394 _AL_FREE(mf->glyphs);
395 *allegro_errno = ENOMEM;
396 return NULL;
397 }
398
399 gl[i]->w = w;
400 gl[i]->h = h;
401 pack_fread(gl[i]->dat, sz, f);
402 }
403
404 return mf;
405 }
406
407
408
409 /* read_font_color:
410 * Helper for read_font, below.
411 */
read_font_color(PACKFILE * pack,int * hmax,int depth)412 static FONT_COLOR_DATA *read_font_color(PACKFILE *pack, int *hmax, int depth)
413 {
414 FONT_COLOR_DATA *cf = NULL;
415 int max = 0, i = 0;
416 BITMAP **bits = NULL;
417
418 cf = _AL_MALLOC(sizeof(FONT_COLOR_DATA));
419 if (!cf) {
420 *allegro_errno = ENOMEM;
421 return NULL;
422 }
423
424 cf->begin = pack_mgetl(pack);
425 cf->end = pack_mgetl(pack) + 1;
426 cf->next = NULL;
427 max = cf->end - cf->begin;
428
429 cf->bitmaps = bits = _AL_MALLOC(sizeof(BITMAP *) * max);
430 if (!bits) {
431 _AL_FREE(cf);
432 *allegro_errno = ENOMEM;
433 return NULL;
434 }
435
436 for (i = 0; i < max; i++) {
437 /* Do not allow colour conversions for 8 bit bitmaps, but require it for
438 * all other colour depths.
439 */
440 bits[i] = read_bitmap(pack, depth, depth!=8);
441 if (!bits[i]) {
442 while (i) {
443 i--;
444 destroy_bitmap(bits[i]);
445 }
446 _AL_FREE(bits);
447 _AL_FREE(cf);
448 *allegro_errno = ENOMEM;
449 return 0;
450 }
451
452 if (bits[i]->h > *hmax)
453 *hmax = bits[i]->h;
454 }
455
456 return cf;
457 }
458
459
460
461 /* read_font:
462 * Reads a new style, Unicode format font from a file.
463 */
read_font(PACKFILE * pack)464 static FONT *read_font(PACKFILE *pack)
465 {
466 FONT *f = NULL;
467 int num_ranges = 0;
468 int height = 0;
469 int depth;
470
471 f = _AL_MALLOC(sizeof(FONT));
472 if (!f) {
473 *allegro_errno = ENOMEM;
474 return NULL;
475 }
476
477 f->data = NULL;
478
479 num_ranges = pack_mgetw(pack);
480 while (num_ranges--) {
481 depth = pack_getc(pack);
482 if (depth == 1 || depth == 255) {
483 FONT_MONO_DATA *mf = 0, *iter = (FONT_MONO_DATA *)f->data;
484
485 f->vtable = font_vtable_mono;
486
487 mf = read_font_mono(pack, &height);
488 if (!mf) {
489 destroy_font(f);
490 return NULL;
491 }
492
493 if (!iter)
494 f->data = mf;
495 else {
496 while (iter->next) iter = iter->next;
497 iter->next = mf;
498 }
499 }
500 else {
501 FONT_COLOR_DATA *cf = NULL, *iter = (FONT_COLOR_DATA *)f->data;
502
503 /* Older versions of Allegro use `0' to indicate a colour font */
504 if (depth == 0)
505 depth = 8;
506
507 f->vtable = font_vtable_color;
508
509 cf = read_font_color(pack, &height, depth);
510 if (!cf) {
511 destroy_font(f);
512 return NULL;
513 }
514
515 if (!iter)
516 f->data = cf;
517 else {
518 while (iter->next) iter = iter->next;
519 iter->next = cf;
520 }
521 }
522 }
523
524 f->height = height;
525 return f;
526 }
527
528
529
530 /* read_palette:
531 * Reads a palette from a file.
532 */
read_palette(PACKFILE * f,int size)533 static RGB *read_palette(PACKFILE *f, int size)
534 {
535 RGB *p;
536 int c, x;
537
538 p = _AL_MALLOC_ATOMIC(sizeof(PALETTE));
539 if (!p) {
540 *allegro_errno = ENOMEM;
541 return NULL;
542 }
543
544 for (c=0; c<size; c++) {
545 p[c].r = pack_getc(f) >> 2;
546 p[c].g = pack_getc(f) >> 2;
547 p[c].b = pack_getc(f) >> 2;
548 }
549
550 x = 0;
551 while (c < PAL_SIZE) {
552 p[c] = p[x];
553 c++;
554 x++;
555 if (x >= size)
556 x = 0;
557 }
558
559 return p;
560 }
561
562
563
564 /* read_sample:
565 * Reads a sample from a file.
566 */
read_sample(PACKFILE * f)567 static SAMPLE *read_sample(PACKFILE *f)
568 {
569 signed short bits;
570 SAMPLE *s;
571
572 s = _AL_MALLOC(sizeof(SAMPLE));
573 if (!s) {
574 *allegro_errno = ENOMEM;
575 return NULL;
576 }
577
578 bits = pack_mgetw(f);
579
580 if (bits < 0) {
581 s->bits = -bits;
582 s->stereo = TRUE;
583 }
584 else {
585 s->bits = bits;
586 s->stereo = FALSE;
587 }
588
589 s->freq = pack_mgetw(f);
590 s->len = pack_mgetl(f);
591 s->priority = 128;
592 s->loop_start = 0;
593 s->loop_end = s->len;
594 s->param = 0;
595
596 if (s->bits == 8) {
597 s->data = read_block(f, s->len * ((s->stereo) ? 2 : 1), 0);
598 }
599 else {
600 s->data = _AL_MALLOC_ATOMIC(s->len * sizeof(short) * ((s->stereo) ? 2 : 1));
601 if (s->data) {
602 int i;
603
604 for (i=0; i < (int)s->len * ((s->stereo) ? 2 : 1); i++) {
605 ((unsigned short *)s->data)[i] = pack_igetw(f);
606 }
607
608 if (pack_ferror(f)) {
609 _AL_FREE(s->data);
610 s->data = NULL;
611 }
612 }
613 }
614 if (!s->data) {
615 _AL_FREE(s);
616 return NULL;
617 }
618
619 LOCK_DATA(s, sizeof(SAMPLE));
620 LOCK_DATA(s->data, s->len * ((s->bits==8) ? 1 : sizeof(short)) * ((s->stereo) ? 2 : 1));
621
622 return s;
623 }
624
625
626
627 /* read_midi:
628 * Reads MIDI data from a datafile (this is not the same thing as the
629 * standard midi file format).
630 */
read_midi(PACKFILE * f)631 static MIDI *read_midi(PACKFILE *f)
632 {
633 MIDI *m;
634 int c;
635
636 m = _AL_MALLOC(sizeof(MIDI));
637 if (!m) {
638 *allegro_errno = ENOMEM;
639 return NULL;
640 }
641
642 for (c=0; c<MIDI_TRACKS; c++) {
643 m->track[c].len = 0;
644 m->track[c].data = NULL;
645 }
646
647 m->divisions = pack_mgetw(f);
648
649 for (c=0; c<MIDI_TRACKS; c++) {
650 m->track[c].len = pack_mgetl(f);
651 if (m->track[c].len > 0) {
652 m->track[c].data = read_block(f, m->track[c].len, 0);
653 if (!m->track[c].data) {
654 unload_midi(m);
655 return NULL;
656 }
657 }
658 }
659
660 LOCK_DATA(m, sizeof(MIDI));
661
662 for (c=0; c<MIDI_TRACKS; c++) {
663 if (m->track[c].data) {
664 LOCK_DATA(m->track[c].data, m->track[c].len);
665 }
666 }
667
668 return m;
669 }
670
671
672
673 /* read_rle_sprite:
674 * Reads an RLE compressed sprite from a file, allocating memory for it.
675 */
read_rle_sprite(PACKFILE * f,int bits)676 static RLE_SPRITE *read_rle_sprite(PACKFILE *f, int bits)
677 {
678 int x, y, w, h, c, r, g, b, a;
679 int destbits, size, rgba;
680 RLE_SPRITE *s;
681 BITMAP *b1, *b2;
682 unsigned int eol_marker;
683 signed short s16;
684 signed short *p16;
685 int32_t *p32;
686
687 if (bits < 0) {
688 bits = -bits;
689 rgba = TRUE;
690 }
691 else
692 rgba = FALSE;
693
694 w = pack_mgetw(f);
695 h = pack_mgetw(f);
696 size = pack_mgetl(f);
697
698 s = _AL_MALLOC(sizeof(RLE_SPRITE) + size);
699 if (!s) {
700 *allegro_errno = ENOMEM;
701 return NULL;
702 }
703
704 s->w = w;
705 s->h = h;
706 s->color_depth = bits;
707 s->size = size;
708
709 switch (bits) {
710
711 case 8:
712 /* easy! */
713 pack_fread(s->dat, size, f);
714 break;
715
716 case 15:
717 case 16:
718 /* read hicolor data */
719 p16 = (signed short *)s->dat;
720 eol_marker = (bits == 15) ? MASK_COLOR_15 : MASK_COLOR_16;
721
722 for (y=0; y<h; y++) {
723 s16 = pack_igetw(f);
724
725 while ((unsigned short)s16 != MASK_COLOR_16) {
726 if (s16 < 0) {
727 /* skip count */
728 *p16 = s16;
729 p16++;
730 }
731 else {
732 /* solid run */
733 x = s16;
734 *p16 = s16;
735 p16++;
736
737 while (x-- > 0) {
738 c = pack_igetw(f);
739 r = _rgb_scale_5[(c >> 11) & 0x1F];
740 g = _rgb_scale_6[(c >> 5) & 0x3F];
741 b = _rgb_scale_5[c & 0x1F];
742 *p16 = makecol_depth(bits, r, g, b);
743 p16++;
744 }
745 }
746
747 s16 = pack_igetw(f);
748 }
749
750 /* end of line */
751 *p16 = eol_marker;
752 p16++;
753 }
754 break;
755
756 case 24:
757 case 32:
758 /* read truecolor data */
759 p32 = (int32_t *)s->dat;
760 eol_marker = (bits == 24) ? MASK_COLOR_24 : MASK_COLOR_32;
761
762 for (y=0; y<h; y++) {
763 c = pack_igetl(f);
764
765 while ((uint32_t)c != MASK_COLOR_32) {
766 if (c < 0) {
767 /* skip count */
768 *p32 = c;
769 p32++;
770 }
771 else {
772 /* solid run */
773 x = c;
774 *p32 = c;
775 p32++;
776
777 while (x-- > 0) {
778 r = pack_getc(f);
779 g = pack_getc(f);
780 b = pack_getc(f);
781
782 if (rgba)
783 a = pack_getc(f);
784 else
785 a = 0;
786
787 *p32 = makeacol_depth(bits, r, g, b, a);
788
789 p32++;
790 }
791 }
792
793 c = pack_igetl(f);
794 }
795
796 /* end of line */
797 *p32 = eol_marker;
798 p32++;
799 }
800 break;
801 }
802
803 destbits = _color_load_depth(bits, rgba);
804
805 if (destbits != bits) {
806 b1 = create_bitmap_ex(bits, s->w, s->h);
807 if (!b1) {
808 destroy_rle_sprite(s);
809 *allegro_errno = ENOMEM;
810 return NULL;
811 }
812
813 clear_to_color(b1, bitmap_mask_color(b1));
814 draw_rle_sprite(b1, s, 0, 0);
815
816 b2 = create_bitmap_ex(destbits, s->w, s->h);
817 if (!b2) {
818 destroy_rle_sprite(s);
819 destroy_bitmap(b1);
820 *allegro_errno = ENOMEM;
821 return NULL;
822 }
823
824 blit(b1, b2, 0, 0, 0, 0, s->w, s->h);
825
826 destroy_rle_sprite(s);
827 s = get_rle_sprite(b2);
828
829 destroy_bitmap(b1);
830 destroy_bitmap(b2);
831 }
832
833 return s;
834 }
835
836
837
838 /* read_compiled_sprite:
839 * Reads a compiled sprite from a file, allocating memory for it.
840 */
read_compiled_sprite(PACKFILE * f,int planar,int bits)841 static COMPILED_SPRITE *read_compiled_sprite(PACKFILE *f, int planar, int bits)
842 {
843 BITMAP *b;
844 COMPILED_SPRITE *s;
845
846 b = read_bitmap(f, bits, TRUE);
847 if (!b)
848 return NULL;
849
850 if (!_compile_sprites)
851 return (COMPILED_SPRITE *)b;
852
853 s = get_compiled_sprite(b, planar);
854 if (!s)
855 *allegro_errno = ENOMEM;
856
857 destroy_bitmap(b);
858
859 return s;
860 }
861
862
863
864 /* read_old_datafile:
865 * Helper for reading old-format datafiles (only needed for backward
866 * compatibility).
867 */
read_old_datafile(PACKFILE * f,void (* callback)(DATAFILE *))868 static DATAFILE *read_old_datafile(PACKFILE *f, void (*callback)(DATAFILE *))
869 {
870 DATAFILE *dat;
871 int size;
872 int type;
873 int c;
874
875 size = pack_mgetw(f);
876 if (size == EOF) {
877 pack_fclose(f);
878 return NULL;
879 }
880
881 dat = _AL_MALLOC(sizeof(DATAFILE)*(size+1));
882 if (!dat) {
883 pack_fclose(f);
884 *allegro_errno = ENOMEM;
885 return NULL;
886 }
887
888 for (c=0; c<=size; c++) {
889 dat[c].type = DAT_END;
890 dat[c].dat = NULL;
891 dat[c].size = 0;
892 dat[c].prop = NULL;
893 }
894
895 *allegro_errno = 0;
896
897 for (c=0; c<size; c++) {
898
899 type = pack_mgetw(f);
900
901 switch (type) {
902
903 case V1_DAT_FONT:
904 case V1_DAT_FONT_8x8:
905 dat[c].type = DAT_FONT;
906 dat[c].dat = read_font_fixed(f, 8, OLD_FONT_SIZE);
907 dat[c].size = 0;
908 break;
909
910 case V1_DAT_FONT_PROP:
911 dat[c].type = DAT_FONT;
912 dat[c].dat = read_font_prop(f, OLD_FONT_SIZE);
913 dat[c].size = 0;
914 break;
915
916 case V1_DAT_BITMAP:
917 case V1_DAT_BITMAP_256:
918 dat[c].type = DAT_BITMAP;
919 dat[c].dat = read_bitmap(f, 8, TRUE);
920 dat[c].size = 0;
921 break;
922
923 case V1_DAT_BITMAP_16:
924 dat[c].type = DAT_BITMAP;
925 dat[c].dat = read_bitmap(f, 4, FALSE);
926 dat[c].size = 0;
927 break;
928
929 case V1_DAT_SPRITE_256:
930 dat[c].type = DAT_BITMAP;
931 pack_mgetw(f);
932 dat[c].dat = read_bitmap(f, 8, TRUE);
933 dat[c].size = 0;
934 break;
935
936 case V1_DAT_SPRITE_16:
937 dat[c].type = DAT_BITMAP;
938 pack_mgetw(f);
939 dat[c].dat = read_bitmap(f, 4, FALSE);
940 dat[c].size = 0;
941 break;
942
943 case V1_DAT_PALETTE:
944 case V1_DAT_PALETTE_256:
945 dat[c].type = DAT_PALETTE;
946 dat[c].dat = read_palette(f, PAL_SIZE);
947 dat[c].size = sizeof(PALETTE);
948 break;
949
950 case V1_DAT_PALETTE_16:
951 dat[c].type = DAT_PALETTE;
952 dat[c].dat = read_palette(f, 16);
953 dat[c].size = 0;
954 break;
955
956 case V1_DAT_SAMPLE:
957 dat[c].type = DAT_SAMPLE;
958 dat[c].dat = read_sample(f);
959 dat[c].size = 0;
960 break;
961
962 case V1_DAT_MIDI:
963 dat[c].type = DAT_MIDI;
964 dat[c].dat = read_midi(f);
965 dat[c].size = 0;
966 break;
967
968 case V1_DAT_RLE_SPRITE:
969 dat[c].type = DAT_RLE_SPRITE;
970 dat[c].dat = read_rle_sprite(f, 8);
971 dat[c].size = 0;
972 break;
973
974 case V1_DAT_FLI:
975 dat[c].type = DAT_FLI;
976 dat[c].size = pack_mgetl(f);
977 dat[c].dat = read_block(f, dat[c].size, 0);
978 break;
979
980 case V1_DAT_C_SPRITE:
981 dat[c].type = DAT_C_SPRITE;
982 dat[c].dat = read_compiled_sprite(f, FALSE, 8);
983 dat[c].size = 0;
984 break;
985
986 case V1_DAT_XC_SPRITE:
987 dat[c].type = DAT_XC_SPRITE;
988 dat[c].dat = read_compiled_sprite(f, TRUE, 8);
989 dat[c].size = 0;
990 break;
991
992 default:
993 dat[c].type = DAT_DATA;
994 dat[c].size = pack_mgetl(f);
995 dat[c].dat = read_block(f, dat[c].size, 0);
996 break;
997 }
998
999 if (*allegro_errno) {
1000 if (!dat[c].dat)
1001 dat[c].type = DAT_END;
1002 unload_datafile(dat);
1003 pack_fclose(f);
1004 return NULL;
1005 }
1006
1007 if (callback)
1008 callback(dat+c);
1009 }
1010
1011 return dat;
1012 }
1013
1014
1015
1016 /* load_data_object:
1017 * Loads a binary data object from a datafile.
1018 */
load_data_object(PACKFILE * f,long size)1019 static void *load_data_object(PACKFILE *f, long size)
1020 {
1021 return read_block(f, size, 0);
1022 }
1023
1024
1025
1026 /* load_font_object:
1027 * Loads a font object from a datafile.
1028 */
load_font_object(PACKFILE * f,long size)1029 static void *load_font_object(PACKFILE *f, long size)
1030 {
1031 short height = pack_mgetw(f);
1032
1033 if (height > 0)
1034 return read_font_fixed(f, height, LESS_OLD_FONT_SIZE);
1035 else if (height < 0)
1036 return read_font_prop(f, LESS_OLD_FONT_SIZE);
1037 else
1038 return read_font(f);
1039 }
1040
1041
1042
1043 /* load_sample_object:
1044 * Loads a sample object from a datafile.
1045 */
load_sample_object(PACKFILE * f,long size)1046 static void *load_sample_object(PACKFILE *f, long size)
1047 {
1048 return read_sample(f);
1049 }
1050
1051
1052
1053 /* load_midi_object:
1054 * Loads a midifile object from a datafile.
1055 */
load_midi_object(PACKFILE * f,long size)1056 static void *load_midi_object(PACKFILE *f, long size)
1057 {
1058 return read_midi(f);
1059 }
1060
1061
1062
1063 /* load_bitmap_object:
1064 * Loads a bitmap object from a datafile.
1065 */
load_bitmap_object(PACKFILE * f,long size)1066 static void *load_bitmap_object(PACKFILE *f, long size)
1067 {
1068 short bits = pack_mgetw(f);
1069
1070 return read_bitmap(f, bits, TRUE);
1071 }
1072
1073
1074
1075 /* load_rle_sprite_object:
1076 * Loads an RLE sprite object from a datafile.
1077 */
load_rle_sprite_object(PACKFILE * f,long size)1078 static void *load_rle_sprite_object(PACKFILE *f, long size)
1079 {
1080 short bits = pack_mgetw(f);
1081
1082 return read_rle_sprite(f, bits);
1083 }
1084
1085
1086
1087 /* load_compiled_sprite_object:
1088 * Loads a compiled sprite object from a datafile.
1089 */
load_compiled_sprite_object(PACKFILE * f,long size)1090 static void *load_compiled_sprite_object(PACKFILE *f, long size)
1091 {
1092 short bits = pack_mgetw(f);
1093
1094 return read_compiled_sprite(f, FALSE, bits);
1095 }
1096
1097
1098
1099 /* load_xcompiled_sprite_object:
1100 * Loads a mode-X compiled object from a datafile.
1101 */
load_xcompiled_sprite_object(PACKFILE * f,long size)1102 static void *load_xcompiled_sprite_object(PACKFILE *f, long size)
1103 {
1104 short bits = pack_mgetw(f);
1105
1106 return read_compiled_sprite(f, TRUE, bits);
1107 }
1108
1109
1110
1111 /* unload_sample:
1112 * Destroys a sample object.
1113 */
unload_sample(SAMPLE * s)1114 static void unload_sample(SAMPLE *s)
1115 {
1116 if (s) {
1117 if (s->data) {
1118 UNLOCK_DATA(s->data, s->len * ((s->bits==8) ? 1 : sizeof(short)) * ((s->stereo) ? 2 : 1));
1119 _AL_FREE(s->data);
1120 }
1121
1122 UNLOCK_DATA(s, sizeof(SAMPLE));
1123 _AL_FREE(s);
1124 }
1125 }
1126
1127
1128
1129 /* unload_midi:
1130 * Destroys a MIDI object.
1131 */
unload_midi(MIDI * m)1132 static void unload_midi(MIDI *m)
1133 {
1134 int c;
1135
1136 if (m) {
1137 for (c=0; c<MIDI_TRACKS; c++) {
1138 if (m->track[c].data) {
1139 UNLOCK_DATA(m->track[c].data, m->track[c].len);
1140 _AL_FREE(m->track[c].data);
1141 }
1142 }
1143
1144 UNLOCK_DATA(m, sizeof(MIDI));
1145 _AL_FREE(m);
1146 }
1147 }
1148
1149
1150
1151 /* load_object:
1152 * Helper to load an object from a datafile and store it in 'obj'.
1153 * Returns 0 on success and -1 on failure.
1154 */
load_object(DATAFILE * obj,PACKFILE * f,int type)1155 static int load_object(DATAFILE *obj, PACKFILE *f, int type)
1156 {
1157 PACKFILE *ff;
1158 int d, i;
1159
1160 /* load actual data */
1161 ff = pack_fopen_chunk(f, FALSE);
1162
1163 if (ff) {
1164 d = ff->normal.todo;
1165
1166 /* look for a load function */
1167 for (i=0; i<MAX_DATAFILE_TYPES; i++) {
1168 if (_datafile_type[i].type == type) {
1169 obj->dat = _datafile_type[i].load(ff, d);
1170 goto Found;
1171 }
1172 }
1173
1174 /* if not found, load binary data */
1175 obj->dat = load_data_object(ff, d);
1176
1177 Found:
1178 pack_fclose_chunk(ff);
1179
1180 if (!obj->dat)
1181 return -1;
1182
1183 obj->type = type;
1184 obj->size = d;
1185 return 0;
1186 }
1187
1188 return -1;
1189 }
1190
1191
1192
1193 /* _load_property:
1194 * Helper to load a property from a datafile and store it in 'prop'.
1195 * Returns 0 on success and -1 on failure.
1196 */
_load_property(DATAFILE_PROPERTY * prop,PACKFILE * f)1197 int _load_property(DATAFILE_PROPERTY *prop, PACKFILE *f)
1198 {
1199 int type, size;
1200 char *p;
1201
1202 type = pack_mgetl(f);
1203 size = pack_mgetl(f);
1204
1205 prop->type = type;
1206 prop->dat = _AL_MALLOC_ATOMIC(size+1); /* '1' for end-of-string delimiter */
1207 if (!prop->dat) {
1208 *allegro_errno = ENOMEM;
1209 pack_fseek(f, size);
1210 return -1;
1211 }
1212
1213 /* read the property */
1214 pack_fread(prop->dat, size, f);
1215 prop->dat[size] = 0;
1216
1217 /* convert to current encoding format if needed */
1218 if (need_uconvert(prop->dat, U_UTF8, U_CURRENT)) {
1219 int length = uconvert_size(prop->dat, U_UTF8, U_CURRENT);
1220 p = _AL_MALLOC_ATOMIC(length);
1221 if (!p) {
1222 *allegro_errno = ENOMEM;
1223 return -1;
1224 }
1225
1226 do_uconvert(prop->dat, U_UTF8, p, U_CURRENT, length);
1227 _AL_FREE(prop->dat);
1228 prop->dat = p;
1229 }
1230
1231 return 0;
1232 }
1233
1234
1235
1236 /* _add_property:
1237 * Helper to add a new property to a property list. Returns 0 on
1238 * success or -1 on failure.
1239 */
_add_property(DATAFILE_PROPERTY ** list,DATAFILE_PROPERTY * prop)1240 int _add_property(DATAFILE_PROPERTY **list, DATAFILE_PROPERTY *prop)
1241 {
1242 DATAFILE_PROPERTY *iter;
1243 int length = 0;
1244
1245 ASSERT(list);
1246 ASSERT(prop);
1247
1248 /* find the length of the list */
1249 if (*list) {
1250 iter = *list;
1251 while (iter->type != DAT_END) {
1252 length++;
1253 iter++;
1254 }
1255 }
1256
1257 /* grow the list */
1258 *list = _al_sane_realloc(*list, sizeof(DATAFILE_PROPERTY)*(length+2));
1259 if (!(*list)) {
1260 *allegro_errno = ENOMEM;
1261 return -1;
1262 }
1263
1264 /* copy the new property */
1265 (*list)[length] = *prop;
1266
1267 /* set end-of-array marker */
1268 (*list)[length+1].type = DAT_END;
1269 (*list)[length+1].dat = NULL;
1270
1271 return 0;
1272 }
1273
1274
1275
1276 /* _destroy_property_list:
1277 * Helper to destroy a property list.
1278 */
_destroy_property_list(DATAFILE_PROPERTY * list)1279 void _destroy_property_list(DATAFILE_PROPERTY *list)
1280 {
1281 int c;
1282
1283 for (c=0; list[c].type != DAT_END; c++) {
1284 if (list[c].dat)
1285 _AL_FREE(list[c].dat);
1286 }
1287
1288 _AL_FREE(list);
1289 }
1290
1291
1292
1293 /* load_file_object:
1294 * Loads a datafile object.
1295 */
load_file_object(PACKFILE * f,long size)1296 static void *load_file_object(PACKFILE *f, long size)
1297 {
1298 DATAFILE *dat;
1299 DATAFILE_PROPERTY prop, *list;
1300 int count, c, type, failed;
1301
1302 count = pack_mgetl(f);
1303
1304 dat = _AL_MALLOC(sizeof(DATAFILE)*(count+1));
1305 if (!dat) {
1306 *allegro_errno = ENOMEM;
1307 return NULL;
1308 }
1309
1310 list = NULL;
1311 failed = FALSE;
1312
1313 /* search the packfile for properties or objects */
1314 for (c=0; c<count;) {
1315 type = pack_mgetl(f);
1316
1317 if (type == DAT_PROPERTY) {
1318 if ((_load_property(&prop, f) != 0) || (_add_property(&list, &prop) != 0)) {
1319 failed = TRUE;
1320 break;
1321 }
1322 }
1323 else {
1324 if (load_object(&dat[c], f, type) != 0) {
1325 failed = TRUE;
1326 break;
1327 }
1328
1329 /* attach the property list to the object */
1330 dat[c].prop = list;
1331 list = NULL;
1332
1333 if (datafile_callback)
1334 datafile_callback(dat+c);
1335
1336 c++;
1337 }
1338 }
1339
1340 /* set end-of-array marker */
1341 dat[c].type = DAT_END;
1342 dat[c].dat = NULL;
1343
1344 /* destroy the property list if not assigned to an object */
1345 if (list)
1346 _destroy_property_list(list);
1347
1348 /* gracefully handle failure */
1349 if (failed) {
1350 unload_datafile(dat);
1351 _AL_FREE(dat);
1352 dat = NULL;
1353 }
1354
1355 return dat;
1356 }
1357
1358
1359
1360 /* load_datafile:
1361 * Loads an entire data file into memory, and returns a pointer to it.
1362 * On error, sets errno and returns NULL.
1363 */
load_datafile(AL_CONST char * filename)1364 DATAFILE *load_datafile(AL_CONST char *filename)
1365 {
1366 ASSERT(filename);
1367 return load_datafile_callback(filename, NULL);
1368 }
1369
1370
1371
1372 /* load_datafile_callback:
1373 * Loads an entire data file into memory, and returns a pointer to it.
1374 * On error, sets errno and returns NULL.
1375 */
load_datafile_callback(AL_CONST char * filename,void (* callback)(DATAFILE *))1376 DATAFILE *load_datafile_callback(AL_CONST char *filename, void (*callback)(DATAFILE *))
1377 {
1378 PACKFILE *f;
1379 DATAFILE *dat;
1380 int type;
1381 ASSERT(filename);
1382
1383 f = pack_fopen(filename, F_READ_PACKED);
1384 if (!f)
1385 return NULL;
1386
1387 if ((f->normal.flags & PACKFILE_FLAG_CHUNK) && (!(f->normal.flags & PACKFILE_FLAG_EXEDAT)))
1388 type = (_packfile_type == DAT_FILE) ? DAT_MAGIC : 0;
1389 else
1390 type = pack_mgetl(f);
1391
1392 if (type == V1_DAT_MAGIC) {
1393 dat = read_old_datafile(f, callback);
1394 }
1395 else if (type == DAT_MAGIC) {
1396 datafile_callback = callback;
1397 dat = load_file_object(f, 0);
1398 datafile_callback = NULL;
1399 }
1400 else
1401 dat = NULL;
1402
1403 pack_fclose(f);
1404 return dat;
1405 }
1406
1407
1408
1409 /* create_datafile_index
1410 * Reads offsets of all objects inside datafile.
1411 * On error, sets errno and returns NULL.
1412 */
create_datafile_index(AL_CONST char * filename)1413 DATAFILE_INDEX *create_datafile_index(AL_CONST char *filename)
1414 {
1415 PACKFILE *f;
1416 DATAFILE_INDEX *index;
1417 long pos = 4;
1418 int type, count, skip, i;
1419
1420 ASSERT(filename);
1421
1422 f = pack_fopen(filename, F_READ_PACKED);
1423 if (!f)
1424 return NULL;
1425
1426 if ((f->normal.flags & PACKFILE_FLAG_CHUNK) && (!(f->normal.flags & PACKFILE_FLAG_EXEDAT)))
1427 type = (_packfile_type == DAT_FILE) ? DAT_MAGIC : 0;
1428 else {
1429 type = pack_mgetl(f); pos += 4;
1430 }
1431
1432 /* only support V2 datafile format */
1433 if (type != DAT_MAGIC)
1434 return NULL;
1435
1436 count = pack_mgetl(f); pos += 4;
1437
1438 index = _AL_MALLOC(sizeof(DATAFILE_INDEX));
1439 if (!index) {
1440 pack_fclose(f);
1441 *allegro_errno = ENOMEM;
1442 return NULL;
1443 }
1444
1445 index->filename = _al_ustrdup(filename);
1446 if (!index->filename) {
1447 pack_fclose(f);
1448 _AL_FREE(index);
1449 *allegro_errno = ENOMEM;
1450 return NULL;
1451 }
1452
1453 index->offset = _AL_MALLOC(sizeof(long) * count);
1454 if (!index->offset) {
1455 pack_fclose(f);
1456 _AL_FREE(index->filename);
1457 _AL_FREE(index);
1458 *allegro_errno = ENOMEM;
1459 return NULL;
1460 }
1461
1462 for (i = 0; i < count; ++i) {
1463 index->offset[i] = pos;
1464
1465 /* Skip properties */
1466 while (pos += 4, pack_mgetl(f) == DAT_PROPERTY) {
1467
1468 /* Skip property name */
1469 pack_fseek(f, 4); pos += 4;
1470
1471 /* Skip rest of property */
1472 skip = pack_mgetl(f); pos += 4; /* Get property size */
1473 pack_fseek(f, skip); pos += skip;
1474 }
1475
1476 /* Skip rest of object */
1477 skip = pack_mgetl(f) + 4; pos += 4;
1478 pack_fseek(f, skip); pos += skip;
1479
1480 }
1481 pack_fclose(f);
1482 return index;
1483 }
1484
1485
1486
1487 /* load_datafile_object:
1488 * Loads a single object from a datafile.
1489 */
load_datafile_object(AL_CONST char * filename,AL_CONST char * objectname)1490 DATAFILE *load_datafile_object(AL_CONST char *filename, AL_CONST char *objectname)
1491 {
1492 PACKFILE *f;
1493 DATAFILE *dat;
1494 DATAFILE_PROPERTY prop, *list;
1495 char parent[1024], child[1024], tmp[8];
1496 char *bufptr, *prevptr, *separator;
1497 int count, c, type, size, found;
1498
1499 ASSERT(filename);
1500 ASSERT(objectname);
1501
1502 /* concatenate to filename#objectname */
1503 ustrzcpy(parent, sizeof(parent), filename);
1504
1505 if (ustrcmp(parent, uconvert_ascii("#", tmp)) != 0)
1506 ustrzcat(parent, sizeof(parent), uconvert_ascii("#", tmp));
1507
1508 ustrzcat(parent, sizeof(parent), objectname);
1509
1510 /* split into path and actual objectname (for nested files) */
1511 prevptr = bufptr = parent;
1512 separator = NULL;
1513 while ((c = ugetx(&bufptr)) != 0) {
1514 if ((c == '#') || (c == '/') || (c == OTHER_PATH_SEPARATOR))
1515 separator = prevptr;
1516
1517 prevptr = bufptr;
1518 }
1519
1520 ustrzcpy(child, sizeof(child), separator + uwidth (separator));
1521
1522 if (separator == parent)
1523 usetc(separator + uwidth (separator), 0);
1524 else
1525 usetc(separator, 0);
1526
1527 /* open the parent datafile */
1528 f = pack_fopen(parent, F_READ_PACKED);
1529 if (!f)
1530 return NULL;
1531
1532 if ((f->normal.flags & PACKFILE_FLAG_CHUNK) && (!(f->normal.flags & PACKFILE_FLAG_EXEDAT)))
1533 type = (_packfile_type == DAT_FILE) ? DAT_MAGIC : 0;
1534 else
1535 type = pack_mgetl(f);
1536
1537 /* only support V2 datafile format */
1538 if (type != DAT_MAGIC) {
1539 pack_fclose(f);
1540 return NULL;
1541 }
1542
1543 count = pack_mgetl(f);
1544
1545 dat = NULL;
1546 list = NULL;
1547 found = FALSE;
1548
1549 /* search the packfile for properties or objects */
1550 for (c=0; c<count;) {
1551 type = pack_mgetl(f);
1552
1553 if (type == DAT_PROPERTY) {
1554 if ((_load_property(&prop, f) != 0) || (_add_property(&list, &prop) != 0))
1555 break;
1556
1557 if ((prop.type == DAT_NAME) && (ustricmp(prop.dat, child) == 0))
1558 found = TRUE;
1559 }
1560 else {
1561 if (found) {
1562 /* we have found the object, load it */
1563 dat = _AL_MALLOC(sizeof(DATAFILE));
1564 if (!dat) {
1565 *allegro_errno = ENOMEM;
1566 break;
1567 }
1568
1569 if (load_object(dat, f, type) != 0) {
1570 _AL_FREE(dat);
1571 dat = NULL;
1572 break;
1573 }
1574
1575 /* attach the property list to the object */
1576 dat->prop = list;
1577 list = NULL;
1578
1579 break;
1580 }
1581 else {
1582 /* skip an unwanted object */
1583 size = pack_mgetl(f);
1584 pack_fseek(f, size+4); /* '4' for the chunk size */
1585
1586 /* destroy the property list */
1587 if (list) {
1588 _destroy_property_list(list);
1589 list = NULL;
1590 }
1591
1592 c++;
1593 }
1594 }
1595 }
1596
1597 /* destroy the property list if not assigned to an object */
1598 if (list)
1599 _destroy_property_list(list);
1600
1601 pack_fclose(f);
1602 return dat;
1603 }
1604
1605
1606
1607 /* load_datafile_object_indexed
1608 * Loads a single object from a datafile using its offset.
1609 * On error, returns NULL.
1610 */
load_datafile_object_indexed(AL_CONST DATAFILE_INDEX * index,int item)1611 DATAFILE *load_datafile_object_indexed(AL_CONST DATAFILE_INDEX *index, int item)
1612 {
1613 int type;
1614 PACKFILE *f;
1615 DATAFILE *dat;
1616 DATAFILE_PROPERTY prop, *list = NULL;
1617
1618 ASSERT(index);
1619
1620 f = pack_fopen(index->filename, F_READ_PACKED);
1621 if (!f)
1622 return NULL;
1623
1624 dat = _AL_MALLOC(sizeof(DATAFILE));
1625 if (!dat) {
1626 pack_fclose(f);
1627 *allegro_errno = ENOMEM;
1628 return NULL;
1629 }
1630
1631 /* pack_fopen will read first 4 bytes for us */
1632 pack_fseek(f, index->offset[item] - 4);
1633
1634 do
1635 type = pack_mgetl(f);
1636 while (type == DAT_PROPERTY && _load_property(&prop, f) == 0 &&
1637 _add_property(&list, &prop) == 0);
1638
1639
1640 if (load_object(dat, f, type) != 0) {
1641 pack_fclose(f);
1642 _AL_FREE(dat);
1643 _destroy_property_list(list);
1644 return NULL;
1645 }
1646
1647 /* attach the property list to the object */
1648 dat->prop = list;
1649
1650 pack_fclose(f);
1651 return dat;
1652 }
1653
1654
1655
1656 /* _unload_datafile_object:
1657 * Helper to destroy a datafile object.
1658 */
_unload_datafile_object(DATAFILE * dat)1659 void _unload_datafile_object(DATAFILE *dat)
1660 {
1661 int i;
1662
1663 /* destroy the property list */
1664 if (dat->prop)
1665 _destroy_property_list(dat->prop);
1666
1667 /* look for a destructor function */
1668 for (i=0; i<MAX_DATAFILE_TYPES; i++) {
1669 if (_datafile_type[i].type == dat->type) {
1670 if (dat->dat) {
1671 if (_datafile_type[i].destroy)
1672 _datafile_type[i].destroy(dat->dat);
1673 else
1674 _AL_FREE(dat->dat);
1675 }
1676 return;
1677 }
1678 }
1679
1680 /* if not found, just free the data */
1681 if (dat->dat)
1682 _AL_FREE(dat->dat);
1683 }
1684
1685
1686
1687 /* unload_datafile:
1688 * Frees all the objects in a datafile.
1689 */
unload_datafile(DATAFILE * dat)1690 void unload_datafile(DATAFILE *dat)
1691 {
1692 int i;
1693
1694 if (dat) {
1695 for (i=0; dat[i].type != DAT_END; i++)
1696 _unload_datafile_object(dat+i);
1697
1698 _AL_FREE(dat);
1699 }
1700 }
1701
1702
1703
1704 /* unload_datafile_index
1705 * Frees memory used by datafile index
1706 */
destroy_datafile_index(DATAFILE_INDEX * index)1707 void destroy_datafile_index(DATAFILE_INDEX *index)
1708 {
1709 if (index) {
1710 _AL_FREE(index->filename);
1711 _AL_FREE(index->offset);
1712 _AL_FREE(index);
1713 }
1714 }
1715
1716
1717
1718 /* unload_datafile_object:
1719 * Unloads a single datafile object, returned by load_datafile_object().
1720 */
unload_datafile_object(DATAFILE * dat)1721 void unload_datafile_object(DATAFILE *dat)
1722 {
1723 if (dat) {
1724 _unload_datafile_object(dat);
1725 _AL_FREE(dat);
1726 }
1727 }
1728
1729
1730
1731 /* find_datafile_object:
1732 * Returns a pointer to the datafile object with the given name
1733 */
find_datafile_object(AL_CONST DATAFILE * dat,AL_CONST char * objectname)1734 DATAFILE *find_datafile_object(AL_CONST DATAFILE *dat, AL_CONST char *objectname)
1735 {
1736 char name[512];
1737 int recurse = FALSE;
1738 int pos, c;
1739 ASSERT(dat);
1740 ASSERT(objectname);
1741
1742 /* split up the object name */
1743 pos = 0;
1744
1745 while ((c = ugetxc(&objectname)) != 0) {
1746 if ((c == '#') || (c == '/') || (c == OTHER_PATH_SEPARATOR)) {
1747 recurse = TRUE;
1748 break;
1749 }
1750 pos += usetc(name+pos, c);
1751 }
1752
1753 usetc(name+pos, 0);
1754
1755 /* search for the requested object */
1756 for (pos=0; dat[pos].type != DAT_END; pos++) {
1757 if (ustricmp(name, get_datafile_property(dat+pos, DAT_NAME)) == 0) {
1758 if (recurse) {
1759 if (dat[pos].type == DAT_FILE)
1760 return find_datafile_object(dat[pos].dat, objectname);
1761 else
1762 return NULL;
1763 }
1764 else
1765 return (DATAFILE*)dat+pos;
1766 }
1767 }
1768
1769 /* oh dear, the object isn't there... */
1770 return NULL;
1771 }
1772
1773
1774
1775 /* get_datafile_property:
1776 * Returns the specified property string for the datafile object, or
1777 * an empty string if the property does not exist.
1778 */
get_datafile_property(AL_CONST DATAFILE * dat,int type)1779 AL_CONST char *get_datafile_property(AL_CONST DATAFILE *dat, int type)
1780 {
1781 DATAFILE_PROPERTY *prop;
1782 ASSERT(dat);
1783
1784 prop = dat->prop;
1785 if (prop) {
1786 while (prop->type != DAT_END) {
1787 if (prop->type == type)
1788 return (prop->dat) ? prop->dat : empty_string;
1789
1790 prop++;
1791 }
1792 }
1793
1794 return empty_string;
1795 }
1796
1797
1798
1799 /* fixup_datafile:
1800 * For use with compiled datafiles, to initialise them if they are not
1801 * constructed and to convert truecolor images into the appropriate
1802 * pixel format.
1803 */
fixup_datafile(DATAFILE * data)1804 void fixup_datafile(DATAFILE *data)
1805 {
1806 BITMAP *bmp;
1807 RLE_SPRITE *rle;
1808 int i, c, r, g, b, a, x, y;
1809 int bpp, depth;
1810 unsigned char *p8;
1811 unsigned short *p16;
1812 uint32_t *p32;
1813 signed short *s16;
1814 int32_t *s32;
1815 int eol_marker;
1816 ASSERT(data);
1817
1818 /* initialise the datafile if needed */
1819 if (!constructed_datafiles)
1820 initialise_datafile(data);
1821
1822 for (i=0; data[i].type != DAT_END; i++) {
1823
1824 switch (data[i].type) {
1825
1826 case DAT_BITMAP:
1827 /* fix up a bitmap object */
1828 bmp = data[i].dat;
1829 bpp = bitmap_color_depth(bmp);
1830
1831 switch (bpp) {
1832
1833 #ifdef ALLEGRO_COLOR16
1834
1835 case 15:
1836 /* fix up a 15 bit hicolor bitmap */
1837 if (_color_depth == 16) {
1838 GFX_VTABLE *vtable = _get_vtable(16);
1839
1840 if (vtable != NULL) {
1841 depth = 16;
1842 bmp->vtable = vtable;
1843 }
1844 else
1845 depth = 15;
1846 }
1847 else
1848 depth = 15;
1849
1850 for (y=0; y<bmp->h; y++) {
1851 p16 = (unsigned short *)bmp->line[y];
1852
1853 for (x=0; x<bmp->w; x++) {
1854 c = p16[x];
1855 r = _rgb_scale_5[c & 0x1F];
1856 g = _rgb_scale_5[(c >> 5) & 0x1F];
1857 b = _rgb_scale_5[(c >> 10) & 0x1F];
1858 p16[x] = makecol_depth(depth, r, g, b);
1859 }
1860 }
1861 break;
1862
1863
1864 case 16:
1865 /* fix up a 16 bit hicolor bitmap */
1866 if (_color_depth == 15) {
1867 GFX_VTABLE *vtable = _get_vtable(15);
1868
1869 if (vtable != NULL) {
1870 depth = 15;
1871 bmp->vtable = vtable;
1872 }
1873 else
1874 depth = 16;
1875 }
1876 else
1877 depth = 16;
1878
1879 for (y=0; y<bmp->h; y++) {
1880 p16 = (unsigned short *)bmp->line[y];
1881
1882 for (x=0; x<bmp->w; x++) {
1883 c = p16[x];
1884 r = _rgb_scale_5[c & 0x1F];
1885 g = _rgb_scale_6[(c >> 5) & 0x3F];
1886 b = _rgb_scale_5[(c >> 11) & 0x1F];
1887 if (_color_conv & COLORCONV_KEEP_TRANS && depth == 15 &&
1888 c == 0xf83f) g = 8; /* don't end up as mask color */
1889 p16[x] = makecol_depth(depth, r, g, b);
1890 }
1891 }
1892 break;
1893
1894 #endif
1895
1896
1897 #ifdef ALLEGRO_COLOR24
1898
1899 case 24:
1900 /* fix up a 24 bit truecolor bitmap */
1901 for (y=0; y<bmp->h; y++) {
1902 p8 = bmp->line[y];
1903
1904 for (x=0; x<bmp->w; x++) {
1905 c = READ3BYTES(p8+x*3);
1906 r = (c & 0xFF);
1907 g = (c >> 8) & 0xFF;
1908 b = (c >> 16) & 0xFF;
1909 WRITE3BYTES(p8+x*3, makecol24(r, g, b));
1910 }
1911 }
1912 break;
1913
1914 #endif
1915
1916
1917 #ifdef ALLEGRO_COLOR32
1918
1919 case 32:
1920 /* fix up a 32 bit truecolor bitmap */
1921 for (y=0; y<bmp->h; y++) {
1922 p32 = (uint32_t *)bmp->line[y];
1923
1924 for (x=0; x<bmp->w; x++) {
1925 c = p32[x];
1926 r = (c & 0xFF);
1927 g = (c >> 8) & 0xFF;
1928 b = (c >> 16) & 0xFF;
1929 a = (c >> 24) & 0xFF;
1930 p32[x] = makeacol32(r, g, b, a);
1931 }
1932 }
1933 break;
1934
1935 #endif
1936
1937 }
1938 break;
1939
1940
1941 case DAT_RLE_SPRITE:
1942 /* fix up an RLE sprite object */
1943 rle = data[i].dat;
1944 bpp = rle->color_depth;
1945
1946 switch (bpp) {
1947
1948 #ifdef ALLEGRO_COLOR16
1949
1950 case 15:
1951 /* fix up a 15 bit hicolor RLE sprite */
1952 if (_color_depth == 16) {
1953 depth = 16;
1954 rle->color_depth = 16;
1955 eol_marker = MASK_COLOR_16;
1956 }
1957 else {
1958 depth = 15;
1959 eol_marker = MASK_COLOR_15;
1960 }
1961
1962 s16 = (signed short *)rle->dat;
1963
1964 for (y=0; y<rle->h; y++) {
1965 while ((unsigned short)*s16 != MASK_COLOR_15) {
1966 if (*s16 > 0) {
1967 x = *s16;
1968 s16++;
1969 while (x-- > 0) {
1970 c = *s16;
1971 r = _rgb_scale_5[c & 0x1F];
1972 g = _rgb_scale_5[(c >> 5) & 0x1F];
1973 b = _rgb_scale_5[(c >> 10) & 0x1F];
1974 *s16 = makecol_depth(depth, r, g, b);
1975 s16++;
1976 }
1977 }
1978 else
1979 s16++;
1980 }
1981 *s16 = eol_marker;
1982 s16++;
1983 }
1984 break;
1985
1986
1987 case 16:
1988 /* fix up a 16 bit hicolor RLE sprite */
1989 if (_color_depth == 15) {
1990 depth = 15;
1991 rle->color_depth = 15;
1992 eol_marker = MASK_COLOR_15;
1993 }
1994 else {
1995 depth = 16;
1996 eol_marker = MASK_COLOR_16;
1997 }
1998
1999 s16 = (signed short *)rle->dat;
2000
2001 for (y=0; y<rle->h; y++) {
2002 while ((unsigned short)*s16 != MASK_COLOR_16) {
2003 if (*s16 > 0) {
2004 x = *s16;
2005 s16++;
2006 while (x-- > 0) {
2007 c = *s16;
2008 r = _rgb_scale_5[c & 0x1F];
2009 g = _rgb_scale_6[(c >> 5) & 0x3F];
2010 b = _rgb_scale_5[(c >> 11) & 0x1F];
2011 *s16 = makecol_depth(depth, r, g, b);
2012 s16++;
2013 }
2014 }
2015 else
2016 s16++;
2017 }
2018 *s16 = eol_marker;
2019 s16++;
2020 }
2021 break;
2022
2023 #endif
2024
2025
2026 #ifdef ALLEGRO_COLOR24
2027
2028 case 24:
2029 /* fix up a 24 bit truecolor RLE sprite */
2030 if (_color_depth == 32) {
2031 depth = 32;
2032 rle->color_depth = 32;
2033 eol_marker = MASK_COLOR_32;
2034 }
2035 else {
2036 depth = 24;
2037 eol_marker = MASK_COLOR_24;
2038 }
2039
2040 s32 = (int32_t *)rle->dat;
2041
2042 for (y=0; y<rle->h; y++) {
2043 while ((uint32_t)*s32 != MASK_COLOR_24) {
2044 if (*s32 > 0) {
2045 x = *s32;
2046 s32++;
2047 while (x-- > 0) {
2048 c = *s32;
2049 r = (c & 0xFF);
2050 g = (c>>8) & 0xFF;
2051 b = (c>>16) & 0xFF;
2052 *s32 = makecol_depth(depth, r, g, b);
2053 s32++;
2054 }
2055 }
2056 else
2057 s32++;
2058 }
2059 *s32 = eol_marker;
2060 s32++;
2061 }
2062 break;
2063
2064 #endif
2065
2066
2067 #ifdef ALLEGRO_COLOR32
2068
2069 case 32:
2070 /* fix up a 32 bit truecolor RLE sprite */
2071 if (_color_depth == 24) {
2072 depth = 24;
2073 rle->color_depth = 24;
2074 eol_marker = MASK_COLOR_24;
2075 }
2076 else {
2077 depth = 32;
2078 eol_marker = MASK_COLOR_32;
2079 }
2080
2081 s32 = (int32_t *)rle->dat;
2082
2083 for (y=0; y<rle->h; y++) {
2084 while ((uint32_t)*s32 != MASK_COLOR_32) {
2085 if (*s32 > 0) {
2086 x = *s32;
2087 s32++;
2088 while (x-- > 0) {
2089 c = *s32;
2090 r = (c & 0xFF);
2091 g = (c>>8) & 0xFF;
2092 b = (c>>16) & 0xFF;
2093 if (depth == 32) {
2094 a = (c>>24) & 0xFF;
2095 *s32 = makeacol32(r, g, b, a);
2096 }
2097 else
2098 *s32 = makecol24(r, g, b);
2099 s32++;
2100 }
2101 }
2102 else
2103 s32++;
2104 }
2105 *s32 = eol_marker;
2106 s32++;
2107 }
2108 break;
2109
2110 #endif
2111
2112 }
2113 break;
2114 }
2115 }
2116 }
2117
2118
2119
2120 /* initialise_bitmap:
2121 * Helper used by the output from dat2s/c, for fixing up parts
2122 * of a BITMAP structure that can't be statically initialised.
2123 */
initialise_bitmap(BITMAP * bmp)2124 static void initialise_bitmap(BITMAP *bmp)
2125 {
2126 int i;
2127
2128 for (i=0; _vtable_list[i].vtable; i++) {
2129 if (_vtable_list[i].color_depth == (int)(uintptr_t)bmp->vtable) {
2130 bmp->vtable = _vtable_list[i].vtable;
2131 bmp->write_bank = _stub_bank_switch;
2132 bmp->read_bank = _stub_bank_switch;
2133 bmp->seg = _default_ds();
2134 return;
2135 }
2136 }
2137
2138 ASSERT(FALSE);
2139 }
2140
2141
2142
2143 /* initialise_datafile:
2144 * Helper used by the output from dat2s/c, for fixing up parts
2145 * of the data that can't be statically initialised.
2146 */
initialise_datafile(DATAFILE * data)2147 static void initialise_datafile(DATAFILE *data)
2148 {
2149 int c, c2, color_flag;
2150 FONT *f;
2151 SAMPLE *s;
2152 MIDI *m;
2153
2154 for (c=0; data[c].type != DAT_END; c++) {
2155
2156 switch (data[c].type) {
2157
2158 case DAT_FILE:
2159 initialise_datafile(data[c].dat);
2160 break;
2161
2162 case DAT_BITMAP:
2163 initialise_bitmap((BITMAP *)data[c].dat);
2164 break;
2165
2166 case DAT_FONT:
2167 f = data[c].dat;
2168 color_flag = (int)(uintptr_t)f->vtable;
2169 if (color_flag == 1) {
2170 FONT_COLOR_DATA *cf = (FONT_COLOR_DATA *)f->data;
2171 while (cf) {
2172 for (c2 = cf->begin; c2 < cf->end; c2++)
2173 initialise_bitmap((BITMAP *)cf->bitmaps[c2 - cf->begin]);
2174 cf = cf->next;
2175 }
2176 f->vtable = font_vtable_color;
2177 }
2178 else {
2179 f->vtable = font_vtable_mono;
2180 }
2181 break;
2182
2183 case DAT_SAMPLE:
2184 s = data[c].dat;
2185 LOCK_DATA(s, sizeof(SAMPLE));
2186 LOCK_DATA(s->data, s->len * ((s->bits==8) ? 1 : sizeof(short)) * ((s->stereo) ? 2 : 1));
2187 break;
2188
2189 case DAT_MIDI:
2190 m = data[c].dat;
2191 LOCK_DATA(m, sizeof(MIDI));
2192 for (c2=0; c2<MIDI_TRACKS; c2++) {
2193 if (m->track[c2].data) {
2194 LOCK_DATA(m->track[c2].data, m->track[c2].len);
2195 }
2196 }
2197 break;
2198 }
2199 }
2200 }
2201
2202
2203
2204 /* _construct_datafile:
2205 * Constructor called by the output from dat2s/c.
2206 */
_construct_datafile(DATAFILE * data)2207 void _construct_datafile(DATAFILE *data)
2208 {
2209 /* record that datafiles are constructed */
2210 constructed_datafiles = TRUE;
2211
2212 initialise_datafile(data);
2213 }
2214
2215
2216
2217 /* _initialize_datafile_types:
2218 * Register my loader functions with the code in dataregi.c.
2219 */
2220 #ifdef ALLEGRO_USE_CONSTRUCTOR
2221 CONSTRUCTOR_FUNCTION(void _initialize_datafile_types(void));
2222 #endif
2223
_initialize_datafile_types(void)2224 void _initialize_datafile_types(void)
2225 {
2226 register_datafile_object(DAT_FILE, load_file_object, (void (*)(void *data))unload_datafile );
2227 register_datafile_object(DAT_FONT, load_font_object, (void (*)(void *data))destroy_font );
2228 register_datafile_object(DAT_SAMPLE, load_sample_object, (void (*)(void *data))unload_sample );
2229 register_datafile_object(DAT_MIDI, load_midi_object, (void (*)(void *data))unload_midi );
2230 register_datafile_object(DAT_BITMAP, load_bitmap_object, (void (*)(void *data))destroy_bitmap );
2231 register_datafile_object(DAT_RLE_SPRITE, load_rle_sprite_object, (void (*)(void *data))destroy_rle_sprite );
2232 register_datafile_object(DAT_C_SPRITE, load_compiled_sprite_object, (void (*)(void *data))destroy_compiled_sprite);
2233 register_datafile_object(DAT_XC_SPRITE, load_xcompiled_sprite_object, (void (*)(void *data))destroy_compiled_sprite);
2234 }
2235