1 /*
2 * OpenBOR - http://www.LavaLit.com
3 * -----------------------------------------------------------------------
4 * All rights reserved, see LICENSE in OpenBOR root for details.
5 *
6 * Copyright (c) 2004 - 2011 OpenBOR Team
7 */
8
9 // Functions to load GIF, PCX and BMP files.
10 // Last update: 26-jan-2003
11 // Now loading to screens or bitmaps,
12 // creating them on-the-fly if necessary.
13
14 #include <stdio.h>
15 #include <string.h>
16 #include <assert.h>
17 #include "utils.h"
18 #include "types.h"
19 #include "borendian.h"
20 #include "bitmap.h"
21 #include "screen.h"
22 #include "packfile.h"
23 #include "png.h"
24
25 #ifndef DC
26 #pragma pack (1)
27 #endif
28
29 // ============================== Globals ===============================
30
31 static int handle = -1;
32 static int res[2] = {0, 0}; // Resolution of opened image
33
34 // ============================== BMP loading ===============================
35
36 typedef struct
37 {
38 unsigned short bm;
39 int filesize;
40 int reserved;
41 int picstart;
42 int headersize;
43 int xsize;
44 int ysize;
45 unsigned short numplanes;
46 unsigned short bpp;
47 int compression;
48 int picsize;
49 int hres;
50 int vres;
51 int numcolors_used;
52 int numcolors_important;
53 } s_bmpheader;
54
55 static s_bmpheader bmp_header;
56
57 #if DC || PS2 || GP2X || SYMBIAN
build_bmp_header(s_bmpheader * h,const unsigned char * s)58 static void build_bmp_header(s_bmpheader *h, const unsigned char *s)
59 {
60
61 h->bm = readlsb32(s + 0x00);
62 h->filesize = readlsb32(s + 0x02);
63 h->reserved = readlsb32(s + 0x06);
64 h->picstart = readlsb32(s + 0x0A);
65 h->headersize = readlsb32(s + 0x0E);
66 h->xsize = readlsb32(s + 0x12);
67 h->ysize = readlsb32(s + 0x16);
68 h->numplanes = readlsb32(s + 0x1A);
69 h->bpp = readlsb32(s + 0x1C);
70 h->compression = readlsb32(s + 0x1E);
71 h->picsize = readlsb32(s + 0x22);
72 h->hres = readlsb32(s + 0x26);
73 h->vres = readlsb32(s + 0x2A);
74 h->numcolors_used = readlsb32(s + 0x2E);
75 h->numcolors_important = readlsb32(s + 0x32);
76 }
77 #endif
78
79 // Open a BMP stream
openbmp(char * filename,char * packfilename)80 static int openbmp(char *filename, char *packfilename)
81 {
82
83 #if DC || PS2 || GP2X || SYMBIAN
84 unsigned char mybmpheader[0x36];
85 #endif
86
87 if((handle = openpackfile(filename, packfilename)) == -1)
88 {
89 return 0;
90 }
91 #if DC || PS2 || GP2X || SYMBIAN
92 if(readpackfile(handle, &mybmpheader, 0x36) != 0x36)
93 {
94 #else
95 if(readpackfile(handle, &bmp_header, sizeof(s_bmpheader)) != sizeof(s_bmpheader))
96 {
97 #endif
98 closepackfile(handle);
99 return 0;
100 }
101
102 #if DC || PS2 || GP2X || SYMBIAN
103 build_bmp_header(&bmp_header, mybmpheader);
104 #else
105 bmp_header.bm = SwapLSB16(bmp_header.bm);
106 bmp_header.numplanes = SwapLSB16(bmp_header.numplanes);
107 bmp_header.bpp = SwapLSB16(bmp_header.bpp);
108
109 bmp_header.filesize = SwapLSB32(bmp_header.filesize);
110 bmp_header.reserved = SwapLSB32(bmp_header.reserved);
111 bmp_header.picstart = SwapLSB32(bmp_header.picstart);
112 bmp_header.headersize = SwapLSB32(bmp_header.headersize);
113 bmp_header.xsize = SwapLSB32(bmp_header.xsize);
114 bmp_header.ysize = SwapLSB32(bmp_header.ysize);
115 bmp_header.filesize = SwapLSB32(bmp_header.filesize);
116
117 bmp_header.compression = SwapLSB32(bmp_header.compression);
118 bmp_header.picsize = SwapLSB32(bmp_header.picsize);
119 bmp_header.hres = SwapLSB32(bmp_header.hres);
120 bmp_header.vres = SwapLSB32(bmp_header.vres);
121 bmp_header.numcolors_used = SwapLSB32(bmp_header.numcolors_used);
122 bmp_header.numcolors_important = SwapLSB32(bmp_header.numcolors_important);
123 #endif
124
125 if(bmp_header.bm != 0x4D42 || bmp_header.bpp != 8 || bmp_header.compression)
126 {
127 closepackfile(handle);
128 return 0;
129 }
130 res[0] = bmp_header.xsize;
131 res[1] = bmp_header.ysize;
132 return 1;
133 }
134
135 // Read data from the bitmap file
136 static int readbmp(unsigned char *buf, unsigned char *pal, int maxwidth, int maxheight)
137 {
138
139 unsigned char *linebuffer;
140 int y, s, d;
141 int pb = PAL_BYTES;
142
143 if(buf)
144 {
145 y = 0;
146 while(y < maxheight && y < bmp_header.ysize)
147 {
148 linebuffer = buf + y * maxwidth;
149 seekpackfile(handle, bmp_header.picstart + ((bmp_header.ysize - y - 1)*bmp_header.xsize), SEEK_SET);
150 readpackfile(handle, linebuffer, bmp_header.xsize);
151 ++y;
152 }
153 }
154
155 if(pal && (linebuffer = (unsigned char *)malloc(1024)))
156 {
157 seekpackfile(handle, bmp_header.picstart - 1024, SEEK_SET);
158 readpackfile(handle, linebuffer, 1024);
159 if(pb == 512) // 16bit 565
160 {
161 for(s = 0, d = 0; s < 1024; s += 4, d += 2)
162 {
163 *(unsigned short *)(pal + d) = colour16(linebuffer[s + 2], linebuffer[s + 1], linebuffer[s]);
164 }
165 }
166 else if(pb == 768) // 24bit palette, RGBA-BGR
167 {
168 for(s = 0, d = 0; s < 1024; s += 4, d += 3)
169 {
170 pal[d] = linebuffer[s + 2];
171 pal[d + 1] = linebuffer[s + 1];
172 pal[d + 2] = linebuffer[s];
173 }
174 }
175 else if(pb == 1024)
176 {
177 for(s = 0, d = 0; s < 1024; s += 4, d += 4)
178 {
179 *(unsigned *)(pal + d) = colour32(linebuffer[s + 2], linebuffer[s + 1], linebuffer[s]);
180 }
181 }
182 free(linebuffer);
183 linebuffer = NULL;
184 }
185
186 return 1;
187 }
188
189 //static void closebmp(){
190 // closepackfile(handle);
191 // handle = -1;
192 //}
193
194 //============================ PNG, use libpng =============================
195 static int png_height = 0;
196 static png_structp png_ptr = NULL;
197 static png_infop info_ptr = NULL;
198 static png_bytep *row_pointers = NULL;
199
200 static void png_read_fn(png_structp pngp, png_bytep outp, png_size_t size)
201 {
202 readpackfile(*(int *)(png_get_io_ptr(pngp)), outp, size);
203 }
204
205 static void png_read_destroy_all()
206 {
207 if(png_ptr)
208 {
209 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
210 }
211 info_ptr = NULL;
212 png_ptr = NULL;
213 }
214
215 static void closepng()
216 {
217 int y;
218 png_read_destroy_all();
219 if(row_pointers)
220 {
221 for (y = 0; y < png_height; y++)
222 {
223 free(row_pointers[y]);
224 row_pointers[y] = NULL;
225 }
226 free(row_pointers);
227 row_pointers = NULL;
228 }
229 png_height = 0;
230 if(handle >= 0)
231 {
232 closepackfile(handle);
233 }
234 handle = -1;
235 }
236
237 static int openpng(char *filename, char *packfilename)
238 {
239 unsigned char header[8]; // 8 is the maximum size that can be checked
240 int y;
241
242 if((handle = openpackfile(filename, packfilename)) == -1)
243 {
244 goto openpng_abort;
245 }
246
247 if(readpackfile(handle, header, 8) != 8)
248 {
249 goto openpng_abort;
250 }
251
252 if (png_sig_cmp(header, 0, 8))
253 {
254 goto openpng_abort;
255 }
256
257 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
258
259 if (!png_ptr)
260 {
261 goto openpng_abort;
262 }
263
264 //UT: use customized file read function here, because we use pak file methods instead of stdio
265 png_set_read_fn(png_ptr, &handle, png_read_fn);
266
267 info_ptr = png_create_info_struct(png_ptr);
268 if (!info_ptr)
269 {
270 goto openpng_abort;
271 }
272
273 png_set_sig_bytes(png_ptr, 8);
274 png_read_info(png_ptr, info_ptr);
275
276 //UT: not formal here, but just read what we need since we use only 8bit png for now
277 res[0] = png_get_image_width(png_ptr, info_ptr);
278 png_height = res[1] = png_get_image_height(png_ptr, info_ptr);
279 // should only be a 8bit image by now
280 if (png_get_bit_depth(png_ptr, info_ptr) != 8)
281 {
282 goto openpng_abort;
283 }
284
285 png_read_update_info(png_ptr, info_ptr);
286
287 row_pointers = (png_bytep *) malloc(sizeof(png_bytep) * png_height);
288 for (y = 0; y < png_height; y++)
289 {
290 row_pointers[y] = (png_byte *) malloc(png_get_rowbytes(png_ptr, info_ptr));
291 }
292
293 png_read_image(png_ptr, row_pointers);
294 return 1;
295 openpng_abort:
296 closepng();
297 return 0;
298 }
299
300 static int readpng(unsigned char *buf, unsigned char *pal, int maxwidth, int maxheight)
301 {
302 int i, j, cw, ch;
303 png_colorp png_pal_ptr = 0;
304 int png_pal_num = 0;
305 int pb = PAL_BYTES;
306
307 cw = res[0] > maxwidth ? maxwidth : res[0];
308 ch = res[1] > maxheight ? maxheight : res[1];
309 if(buf)
310 {
311 for(i = 0; i < ch; i++)
312 {
313 memcpy(buf + (maxwidth * i), row_pointers[i], cw);
314 }
315 }
316 if(pal)
317 {
318 if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY)
319 {
320 // set palette for grayscale images
321 for(i = 0; i < 256; i++)
322 {
323 pal[i * 3] = pal[i * 3 + 1] = pal[i * 3 + 2] = i;
324 }
325 return 1;
326 }
327 else if(png_get_PLTE(png_ptr, info_ptr, &png_pal_ptr, &png_pal_num) != PNG_INFO_PLTE ||
328 png_pal_ptr == NULL)
329 {
330 return 0;
331 }
332
333 png_pal_ptr[0].red = png_pal_ptr[0].green = png_pal_ptr[0].blue = 0;
334 if(pb == 512) // 16bit 565
335 {
336 for(i = 0, j = 0; i < 512 && j < png_pal_num; i += 2, j++)
337 {
338 *(unsigned short *)(pal + i) = colour16(png_pal_ptr[j].red, png_pal_ptr[j].green, png_pal_ptr[j].blue);
339 }
340 }
341 else if(pb == 768) // 24bit
342 {
343 for(i = 0; i < png_pal_num; i++)
344 {
345 pal[i * 3] = png_pal_ptr[i].red;
346 pal[i * 3 + 1] = png_pal_ptr[i].green;
347 pal[i * 3 + 2] = png_pal_ptr[i].blue;
348 }
349 }
350 else if(pb == 1024) // 32bit
351 {
352
353 for(i = 0, j = 0; i < 1024 && j < png_pal_num; i += 4, j++)
354 {
355 *(unsigned *)(pal + i) = colour32(png_pal_ptr[j].red, png_pal_ptr[j].green, png_pal_ptr[j].blue);
356 }
357 }
358 }
359 return 1;
360 }
361
362
363 // ============================== GIF loading ===============================
364
365
366 typedef struct
367 {
368 char magic[6];
369 unsigned short screenwidth, screenheight;
370 unsigned char flags;
371 unsigned char background;
372 unsigned char aspect;
373 } gifheaderstruct;
374
375 #if DC || PS2 || GP2X || SYMBIAN
376 #define sizeof_gifheaderstruct 13
377 #endif
378
379 typedef struct
380 {
381 unsigned short left, top, width, height;
382 unsigned char flags;
383 } gifblockstruct;
384
385 #if DC || PS2 || GP2X || SYMBIAN
386 #define sizeof_iblock 9
387 #endif
388
389 static gifheaderstruct gif_header;
390
391 static unsigned char readbyte(int handle)
392 {
393 unsigned char c = 0;
394 readpackfile(handle, &c, 1);
395 return c;
396 }
397
398 #define NO_CODE -1
399
400 static int decodegifblock(int handle, unsigned char *buf, int width, int height, unsigned char bits, gifblockstruct *gb)
401 {
402 short bits2;
403 short codesize;
404 short codesize2;
405 short nextcode;
406 short thiscode;
407 short oldtoken;
408 short currentcode;
409 short oldcode;
410 short bitsleft;
411 short blocksize;
412 int line = 0;
413 int byte = gb->left;
414 int pass = 0;
415
416 unsigned char *p;
417 unsigned char *u;
418
419 unsigned char *q;
420 unsigned char b[255];
421 unsigned char *linebuffer;
422
423 static unsigned char firstcodestack[4096];
424 static unsigned char lastcodestack[4096];
425 static short codestack[4096];
426
427 static short wordmasktable[] = { 0x0000, 0x0001, 0x0003, 0x0007,
428 0x000f, 0x001f, 0x003f, 0x007f,
429 0x00ff, 0x01ff, 0x03ff, 0x07ff,
430 0x0fff, 0x1fff, 0x3fff, 0x7fff
431 };
432
433 static short inctable[] = { 8, 8, 4, 2, 0 };
434 static short startable[] = { 0, 4, 2, 1, 0 };
435
436 p = q = b;
437 bitsleft = 8;
438
439 if (bits < 2 || bits > 8)
440 {
441 return 0; // Bad symbol
442 }
443 bits2 = 1 << bits;
444 nextcode = bits2 + 2;
445 codesize2 = 1 << (codesize = bits + 1);
446 oldcode = oldtoken = NO_CODE;
447
448 linebuffer = buf + (gb->top * width);
449
450 // loop until something breaks
451 for(;;)
452 {
453 if(bitsleft == 8)
454 {
455 if(++p >= q && (((blocksize = (unsigned char)readbyte(handle)) < 1) ||
456 (q = (p = b) + readpackfile(handle, b, blocksize)) < (b + blocksize)))
457 {
458 return 0; // Unexpected EOF
459 }
460 bitsleft = 0;
461 }
462 thiscode = *p;
463 if((currentcode = (codesize + bitsleft)) <= 8)
464 {
465 *p >>= codesize;
466 bitsleft = currentcode;
467 }
468 else
469 {
470 if(++p >= q && (((blocksize = (unsigned char)readbyte(handle)) < 1) ||
471 (q = (p = b) + readpackfile(handle, b, blocksize)) < (b + blocksize)))
472 {
473 return 0; // Unexpected EOF
474 }
475
476 thiscode |= *p << (8 - bitsleft);
477 if(currentcode <= 16)
478 {
479 *p >>= (bitsleft = currentcode - 8);
480 }
481 else
482 {
483 if(++p >= q && (((blocksize = (unsigned char)readbyte(handle)) < 1) ||
484 (q = (p = b) + readpackfile(handle, b, blocksize)) < (b + blocksize)))
485 {
486 return 0; // Unexpected EOF
487 }
488
489 thiscode |= *p << (16 - bitsleft);
490 *p >>= (bitsleft = currentcode - 16);
491 }
492 }
493 thiscode &= wordmasktable[codesize];
494 currentcode = thiscode;
495
496 if(thiscode == (bits2 + 1))
497 {
498 break;
499 }
500 if(thiscode > nextcode)
501 {
502 return 0; // Bad code
503 }
504
505 if(thiscode == bits2)
506 {
507 nextcode = bits2 + 2;
508 codesize2 = 1 << (codesize = (bits + 1));
509 oldtoken = oldcode = NO_CODE;
510 continue;
511 }
512
513 u = firstcodestack;
514
515 if(thiscode == nextcode)
516 {
517 if(oldcode == NO_CODE)
518 {
519 return 0; // Bad code
520 }
521 *u++ = oldtoken;
522 thiscode = oldcode;
523 }
524
525 while(thiscode >= bits2)
526 {
527 *u++ = lastcodestack [thiscode];
528 thiscode = codestack[thiscode];
529 }
530
531 oldtoken = thiscode;
532 do
533 {
534 if(byte < width && line < (height - gb->top))
535 {
536 linebuffer[byte] = thiscode;
537 }
538 byte++;
539 if(byte >= gb->left + gb->width)
540 {
541 byte = gb->left;
542 // check for interlaced image
543 if(gb->flags & 0x40)
544 {
545 line += inctable[pass];
546 if(line >= gb->height)
547 {
548 line = startable[++pass];
549 }
550 }
551 else
552 {
553 ++line;
554 }
555 linebuffer = buf + (width * (gb->top + line));
556 }
557 if (u <= firstcodestack)
558 {
559 break;
560 }
561 thiscode = *--u;
562 }
563 while(1);
564
565 if(nextcode < 4096 && oldcode != NO_CODE)
566 {
567 codestack[nextcode] = oldcode;
568 lastcodestack[nextcode] = oldtoken;
569 if(++nextcode >= codesize2 && codesize < 12)
570 {
571 codesize2 = 1 << ++codesize;
572 }
573 }
574 oldcode = currentcode;
575 }
576 return 1;
577 }
578
579 static void passgifblock(int handle)
580 {
581 int len;
582
583 // Discard extension function code
584 len = readbyte(handle);
585 // Skip all contained blocks
586 while((len = readbyte(handle)) != 0)
587 {
588 seekpackfile(handle, len, SEEK_CUR);
589 }
590 }
591
592 static int opengif(char *filename, char *packfilename)
593 {
594
595 if((handle = openpackfile(filename, packfilename)) == -1)
596 {
597 return 0;
598 }
599
600 #if DC || PS2 || GP2X || SYMBIAN
601 if(readpackfile(handle, &gif_header, sizeof_gifheaderstruct) != sizeof_gifheaderstruct)
602 {
603 #else
604 if(readpackfile(handle, &gif_header, sizeof(gifheaderstruct)) != sizeof(gifheaderstruct))
605 {
606 #endif
607 closepackfile(handle);
608 return 0;
609 }
610 if(gif_header.magic[0] != 'G' || gif_header.magic[1] != 'I' || gif_header.magic[2] != 'F')
611 {
612 // Not a GIF file!
613 closepackfile(handle);
614 return 0;
615 }
616
617 gif_header.screenwidth = SwapLSB16(gif_header.screenwidth);
618 gif_header.screenheight = SwapLSB16(gif_header.screenheight);
619
620 res[0] = gif_header.screenwidth;
621 res[1] = gif_header.screenheight;
622
623 return 1;
624 }
625
626 static int readgif(unsigned char *buf, unsigned char *pal, int maxwidth, int maxheight)
627 {
628
629 gifblockstruct iblock;
630 int bitdepth;
631 int numcolours;
632 int i, j;
633 int done = 0;
634 unsigned char *pbuf;
635 unsigned char c;
636 int pb = PAL_BYTES;
637
638
639 bitdepth = (gif_header.flags & 7) + 1;
640 numcolours = (1 << bitdepth);
641
642
643 // get palette if present and if wanted
644 if(gif_header.flags & 0x80)
645 {
646 if(pal)
647 {
648 if(pb == 512) // 16bit 565
649 {
650 pbuf = malloc(768);
651 if(readpackfile(handle, pbuf, numcolours * 3) != numcolours * 3)
652 {
653 free(pbuf);
654 pbuf = NULL;
655 return 0;
656 }
657 for(i = 0, j = 0; i < 512; i += 2, j += 3)
658 {
659 *(unsigned short *)(pal + i) = colour16(pbuf[j], pbuf[j + 1], pbuf[j + 2]);
660 }
661 free(pbuf);
662 pbuf = NULL;
663 }
664 else if(pb == 768) // 24bit
665 {
666 if(readpackfile(handle, pal, numcolours * 3) != numcolours * 3)
667 {
668 return 0;
669 }
670 }
671 else if(pb == 1024) // 32bit
672 {
673 pbuf = malloc(768);
674 if(readpackfile(handle, pbuf, numcolours * 3) != numcolours * 3)
675 {
676 free(pbuf);
677 pbuf = NULL;
678 return 0;
679 }
680 for(i = 0, j = 0; i < 1024; i += 4, j += 3)
681 {
682 *(unsigned *)(pal + i) = colour32(pbuf[j], pbuf[j + 1], pbuf[j + 2]);
683 }
684 free(pbuf);
685 pbuf = NULL;
686 }
687 }
688 else
689 {
690 seekpackfile(handle, numcolours * 3, SEEK_CUR);
691 }
692 }
693
694 if(!buf)
695 {
696 return 1;
697 }
698
699 // step through the blocks while(c==',' || c=='!' || c==0)
700 while(!done)
701 {
702 if(readpackfile(handle, &c, 1) != 1)
703 {
704 break;
705 }
706 switch(c)
707 {
708 case ',': // An image block
709
710 #if DC || PS2 || GP2X || SYMBIAN
711 if(readpackfile(handle, &iblock, sizeof_iblock) != sizeof_iblock)
712 {
713 #else
714 if(readpackfile(handle, &iblock, sizeof(iblock)) != sizeof(iblock))
715 {
716 #endif
717 return 0;
718 }
719
720 iblock.left = SwapLSB16(iblock.left);
721 iblock.top = SwapLSB16(iblock.top);
722 iblock.width = SwapLSB16(iblock.width);
723 iblock.height = SwapLSB16(iblock.height);
724
725 // get local palette if present and wanted
726 if((iblock.flags & 0x80) && pal)
727 {
728 if(pal)
729 {
730 i = 3 * (1 << ((iblock.flags & 0x0007) + 1));
731 if(readpackfile(handle, pal, i) != numcolours)
732 {
733 return 0;
734 }
735 }
736 else
737 {
738 seekpackfile(handle, numcolours * 3, SEEK_CUR);
739 }
740 }
741
742 // get the initial LZW code bits
743 if(readpackfile(handle, &c, 1) != 1)
744 {
745 return 0;
746 }
747 if(c < 2 || c > 8)
748 {
749 return 0;
750 }
751 if(!decodegifblock(handle, buf, maxwidth, maxheight, c, &iblock))
752 {
753 return 0;
754 }
755 break;
756 case '!':
757 // Extension block, read past it
758 passgifblock(handle);
759 break;
760 case 0:
761 // Isn't this an EOF?
762 break;
763 default:
764 done = 1;
765 }
766 }
767 return 1;
768 }
769
770 // ============================== PCX loading ===============================
771
772 typedef struct
773 {
774 char manufacturer;
775 char version;
776 char encoding;
777 char bitspp;
778 unsigned short xmin, ymin;
779 unsigned short xmax, ymax;
780 unsigned short hres, vres;
781 char unused[48];
782 char reserved;
783 char colorplanes;
784 unsigned short bytesperline;
785 unsigned short paltype;
786 char unused2[58];
787 } s_pcxheader;
788
789 static s_pcxheader pcx_header;
790
791 static int openpcx(char *filename, char *packname)
792 {
793 if((handle = openpackfile(filename, packname)) == -1)
794 {
795 return 0;
796 }
797 if(readpackfile(handle, &pcx_header, 128) != 128)
798 {
799 closepackfile(handle);
800 return 0;
801 }
802
803 pcx_header.xmin = SwapLSB16(pcx_header.xmin);
804 pcx_header.ymin = SwapLSB16(pcx_header.ymin);
805 pcx_header.xmax = SwapLSB16(pcx_header.xmax);
806 pcx_header.ymax = SwapLSB16(pcx_header.ymax);
807 pcx_header.hres = SwapLSB16(pcx_header.hres);
808 pcx_header.vres = SwapLSB16(pcx_header.vres);
809 pcx_header.bytesperline = SwapLSB16(pcx_header.bytesperline);
810 pcx_header.paltype = SwapLSB16(pcx_header.paltype);
811
812 if(pcx_header.colorplanes == 3)
813 {
814 closepackfile(handle);
815 return 0;
816 }
817
818 res[0] = pcx_header.xmax;
819 res[1] = pcx_header.ymax;
820
821 return 1;
822 }
823
824 static int readpcx(unsigned char *buf, unsigned char *pal, int maxwidth, int maxheight)
825 {
826
827 unsigned char *codebuffer;
828 unsigned int i, j;
829 unsigned x, y;
830 unsigned spos; // Searchpos (file)
831 unsigned cpos; // codepos
832 unsigned dpos; // Destination
833 unsigned char repbyte;
834 unsigned char *pbuf;
835 int pb = PAL_BYTES;
836
837 if(buf)
838 {
839
840 if(!(codebuffer = (unsigned char *)malloc(64000)))
841 {
842 return 0;
843 }
844
845 x = 0;
846 y = 0;
847 spos = 0;
848 dpos = 0;
849
850 while(y <= pcx_header.ymax && y < maxheight)
851 {
852
853 seekpackfile(handle, 128 + spos, SEEK_SET);
854
855 if((readpackfile(handle, codebuffer, 64000)) == -1)
856 {
857 free(codebuffer);
858 codebuffer = NULL;
859 return 0;
860 }
861
862 cpos = 0;
863
864 while(cpos < 63990 && y <= pcx_header.ymax && y < maxheight)
865 {
866 if(codebuffer[cpos] > 192)
867 {
868 i = codebuffer[cpos] - 192;
869 repbyte = codebuffer[cpos + 1];
870 do
871 {
872 if(x < maxwidth)
873 {
874 buf[dpos] = (signed char)repbyte;
875 }
876 ++dpos;
877 if((++x) >= pcx_header.bytesperline)
878 {
879 x = 0;
880 ++y;
881 dpos = y * maxwidth;
882 }
883 }
884 while(--i);
885 cpos += 2;
886 }
887 else
888 {
889 if(x < maxwidth)
890 {
891 buf[dpos] = (signed char)codebuffer[cpos];
892 }
893 ++cpos;
894 ++dpos;
895 if((++x) >= pcx_header.bytesperline)
896 {
897 x = 0;
898 ++y;
899 dpos = y * maxwidth;
900 }
901 }
902 }
903 spos += cpos;
904 }
905 free(codebuffer);
906 codebuffer = NULL;
907 }
908
909 if(pal)
910 {
911 seekpackfile(handle, -768, SEEK_END);
912 if(pb == 512) // 16bit 565
913 {
914 pbuf = malloc(768);
915 if(readpackfile(handle, pbuf, 768) != 768)
916 {
917 free(pbuf);
918 pbuf = NULL;
919 return 0;
920 }
921 for(i = 0, j = 0; i < 512; i += 2, j += 3)
922 {
923 *(unsigned short *)(pal + i) = colour16(pbuf[j], pbuf[j + 1], pbuf[j + 2]);
924 }
925 free(pbuf);
926 pbuf = NULL;
927 }
928 else if(pb == 768) // 24bit
929 {
930 if(readpackfile(handle, pal, 768) != 768)
931 {
932 return 0;
933 }
934 }
935 else if(pb == 1024) // 32bit
936 {
937 pbuf = malloc(768);
938 if(readpackfile(handle, pbuf, 768) != 768)
939 {
940 free(pbuf);
941 pbuf = NULL;
942 return 0;
943 }
944 for(i = 0, j = 0; i < 1024; i += 4, j += 3)
945 {
946 *(unsigned *)(pal + i) = colour32(pbuf[j], pbuf[j + 1], pbuf[j + 2]);
947 }
948 free(pbuf);
949 pbuf = NULL;
950 }
951 }
952 return 1;
953 }
954
955 //static void closepcx(){
956 // closepackfile(handle);
957 // handle = -1;
958 //}
959
960 // ============================== auto loading ===============================
961
962 #define OT_GIF 1
963 #define OT_BMP 2
964 #define OT_PCX 3
965 #define OT_PNG 4
966
967 static int open_type = 0;
968
969 static int openimage(char *filename, char *packfile)
970 {
971 char fnam[128];
972 int len = strlen(filename);
973 char *ext = filename + len - 4;
974 open_type = 0;
975
976 if(0 == stricmp(ext, ".png") && openpng(filename, packfile))
977 {
978 open_type = OT_PNG;
979 return 1;
980 }
981 else if(0 == stricmp(ext, ".gif") && opengif(filename, packfile))
982 {
983 open_type = OT_GIF;
984 return 1;
985 }
986 else if(0 == stricmp(ext, ".pcx") && openpcx(filename, packfile))
987 {
988 open_type = OT_PCX;
989 return 1;
990 }
991 else if(0 == stricmp(ext, ".bmp") && openbmp(filename, packfile))
992 {
993 open_type = OT_BMP;
994 return 1;
995 }
996
997 sprintf(fnam, "%s.png", filename);
998 if(openpng(fnam, packfile))
999 {
1000 open_type = OT_PNG;
1001 return 1;
1002 }
1003
1004 sprintf(fnam, "%s.gif", filename);
1005 if(opengif(fnam, packfile))
1006 {
1007 open_type = OT_GIF;
1008 return 1;
1009 }
1010
1011 sprintf(fnam, "%s.pcx", filename);
1012 if(openpcx(fnam, packfile))
1013 {
1014 open_type = OT_PCX;
1015 return 1;
1016 }
1017
1018 sprintf(fnam, "%s.bmp", filename);
1019 if(openbmp(fnam, packfile))
1020 {
1021 open_type = OT_BMP;
1022 return 1;
1023 }
1024 return 0;
1025 }
1026
1027 static int readimage(unsigned char *buf, unsigned char *pal, int maxwidth, int maxheight)
1028 {
1029 int result = 0;
1030 switch(open_type)
1031 {
1032 case OT_GIF:
1033 result = readgif(buf, pal, maxwidth, maxheight);
1034 #ifdef VERBOSE
1035 printf("calling readimage %p %p %d %d with format %s, result is %d\n", buf, pal, maxwidth, maxheight, "GIF", result);
1036 #endif
1037 break;
1038 case OT_PCX:
1039 result = readpcx(buf, pal, maxwidth, maxheight);
1040 #ifdef VERBOSE
1041 printf("calling readimage %p %p %d %d with format %s, result is %d\n", buf, pal, maxwidth, maxheight, "PCX", result);
1042 #endif
1043 break;
1044 case OT_BMP:
1045 result = readbmp(buf, pal, maxwidth, maxheight);
1046 #ifdef VERBOSE
1047 printf("calling readimage %p %p %d %d with format %s, result is %d\n", buf, pal, maxwidth, maxheight, "BMP", result);
1048 #endif
1049 break;
1050 case OT_PNG:
1051 result = readpng(buf, pal, maxwidth, maxheight);
1052 #ifdef VERBOSE
1053 printf("calling readimage %p %p %d %d with format %s, result is %d\n", buf, pal, maxwidth, maxheight, "PNG", result);
1054 #endif
1055 break;
1056 }
1057 if(pal)
1058 {
1059 memset(pal, 0, (PAL_BYTES) >> 8);
1060 }
1061 return result;
1062 }
1063
1064 static void closeimage()
1065 {
1066 if(open_type == OT_PNG)
1067 {
1068 closepng();
1069 }
1070 else
1071 {
1072 if(handle > 0)
1073 {
1074 closepackfile(handle);
1075 }
1076 handle = -1;
1077 }
1078 }
1079
1080 // ============================== Interface ===============================
1081
1082 int loadscreen(char *filename, char *packfile, unsigned char *pal, int format, s_screen **screen)
1083 {
1084 int result;
1085 unsigned char *p;
1086 #ifdef VERBOSE
1087 printf("loadscreen called packfile: %s, filename %s\n", packfile, filename);
1088 #endif
1089 if((*screen))
1090 {
1091 freescreen(screen);
1092 }
1093 if(!openimage(filename, packfile))
1094 {
1095 return 0;
1096 }
1097 if(!(*screen) || ((*screen)->width != res[0] && (*screen)->height != res[1] && (*screen)->pixelformat != format))
1098 {
1099 (*screen) = allocscreen(res[0], res[1], format);
1100 if((*screen) == NULL)
1101 {
1102 closeimage();
1103 assert(0);
1104 return 0;
1105 }
1106 }
1107 if(pal)
1108 {
1109 p = pal;
1110 }
1111 else
1112 {
1113 p = (*screen)->palette;
1114 }
1115 result = readimage((unsigned char *)(*screen)->data, p, (*screen)->width, (*screen)->height);
1116 closeimage();
1117 if(!result)
1118 {
1119 freescreen(screen);
1120 assert(0);
1121 return 0;
1122 }
1123 return 1;
1124 }
1125
1126 s_bitmap *loadbitmap(char *filename, char *packfile, int format)
1127 {
1128 int result;
1129 s_bitmap *bitmap;
1130 int maxwidth, maxheight;
1131
1132 if(!openimage(filename, packfile))
1133 {
1134 return NULL;
1135 }
1136
1137 maxwidth = res[0];
1138 maxheight = res[1];
1139 //if(maxwidth > 4096) maxwidth = 4096;
1140 //if(maxheight > 4096) maxheight = 4096;
1141 bitmap = allocbitmap(maxwidth, maxheight, format);
1142 if(!bitmap)
1143 {
1144 closeimage();
1145 return NULL;
1146 }
1147
1148 result = readimage((unsigned char *)bitmap->data, bitmap->palette, maxwidth, maxheight);
1149 closeimage();
1150 if(!result)
1151 {
1152 freebitmap(bitmap);
1153 return NULL;
1154 }
1155 return bitmap;
1156 }
1157
1158 int loadimagepalette(char *filename, char *packfile, unsigned char *pal)
1159 {
1160 int result;
1161
1162 if(!openimage(filename, packfile))
1163 {
1164 return 0;
1165 }
1166
1167 result = readimage(NULL, pal, 0, 0);
1168 closeimage();
1169 return result;
1170 }
1171