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