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