comparison tools/lib64gfx.c @ 1503:c7b9ef56319b

Factor all the c64 file format specific things into lib64fmt.c
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 11 May 2018 07:41:55 +0300
parents 9ccf973f65ac
children 3265175b24d2
comparison
equal deleted inserted replaced
1502:aa87cb6cf33b 1503:c7b9ef56319b
10 10
11 #define BUF_SIZE_INITIAL (16*1024) 11 #define BUF_SIZE_INITIAL (16*1024)
12 #define BUF_SIZE_GROW (4*1024) 12 #define BUF_SIZE_GROW (4*1024)
13 13
14 14
15 // Based on Pepto's palette, stolen from VICE
16 DMColor dmDefaultC64Palette[C64_NCOLORS] =
17 {
18 { 0x00, 0x00, 0x00, 0xff },
19 { 0xFF, 0xFF, 0xFF, 0xff },
20 { 0x68, 0x37, 0x2B, 0xff },
21 { 0x70, 0xA4, 0xB2, 0xff },
22 { 0x6F, 0x3D, 0x86, 0xff },
23 { 0x58, 0x8D, 0x43, 0xff },
24 { 0x35, 0x28, 0x79, 0xff },
25 { 0xB8, 0xC7, 0x6F, 0xff },
26 { 0x6F, 0x4F, 0x25, 0xff },
27 { 0x43, 0x39, 0x00, 0xff },
28 { 0x9A, 0x67, 0x59, 0xff },
29 { 0x44, 0x44, 0x44, 0xff },
30 { 0x6C, 0x6C, 0x6C, 0xff },
31 { 0x9A, 0xD2, 0x84, 0xff },
32 { 0x6C, 0x5E, 0xB5, 0xff },
33 { 0x95, 0x95, 0x95, 0xff },
34 };
35
36 #define DM_RLE_MARKER 1
37 #define DM_RLE_MASK 2
38
39
40 #define DM_GET_ADDR_LO(addr) ((addr) & 0xff)
41 #define DM_GET_ADDR_HI(addr) (((addr) >> 8) & 0xff)
42
43
44 void dmC64ImageDump(FILE *fh, const DMC64Image *img, const DMC64ImageFormat *fmt) 15 void dmC64ImageDump(FILE *fh, const DMC64Image *img, const DMC64ImageFormat *fmt)
45 { 16 {
46 char typeStr[64]; 17 char typeStr[64];
47 18
48 dmC64GetImageTypeString(typeStr, sizeof(typeStr), img->type, TRUE); 19 dmC64GetImageTypeString(typeStr, sizeof(typeStr), img->type, TRUE);
103 74
104 return buf; 75 return buf;
105 } 76 }
106 77
107 78
108 static BOOL dmCompareAddr16(const Uint8 *buf, const size_t offs, const Uint16 addr) 79 BOOL dmCompareAddr16(const Uint8 *buf, const size_t offs, const Uint16 addr)
109 { 80 {
110 return buf[offs ] == DM_GET_ADDR_LO(addr) && 81 return buf[offs ] == DM_GET_ADDR_LO(addr) &&
111 buf[offs + 1] == DM_GET_ADDR_HI(addr); 82 buf[offs + 1] == DM_GET_ADDR_HI(addr);
112 } 83 }
113 84
269 240
270 return DMERR_OK; 241 return DMERR_OK;
271 } 242 }
272 243
273 244
274 static int dmDecodeGenericRLE(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd, 245 void dmGenericRLEAnalyze(const DMGrowBuf *buf, Uint8 *rleMarker, const int rleType)
246 {
247
248 }
249
250
251 int dmDecodeGenericRLE(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd,
275 const Uint8 rleMarker, const Uint8 rleMask1, const Uint8 rleMask2, const int rleType) 252 const Uint8 rleMarker, const Uint8 rleMask1, const Uint8 rleMask2, const int rleType)
276 { 253 {
277 int res; 254 int res;
278 255
279 if ((res = dmGrowBufAlloc(dst, BUF_SIZE_INITIAL, BUF_SIZE_GROW)) != DMERR_OK) 256 if ((res = dmGrowBufAlloc(dst, BUF_SIZE_INITIAL, BUF_SIZE_GROW)) != DMERR_OK)
333 err: 310 err:
334 return res; 311 return res;
335 } 312 }
336 313
337 314
338 static int dmDecodeGenericRLEAlloc(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd, 315 int dmDecodeGenericRLEAlloc(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd,
339 const Uint8 rleMarker, const Uint8 rleMask1, const Uint8 rleMask2, const int rleType) 316 const Uint8 rleMarker, const Uint8 rleMask1, const Uint8 rleMask2, const int rleType)
340 { 317 {
341 int res; 318 int res;
342 if ((res = dmGrowBufAlloc(dst, BUF_SIZE_INITIAL, BUF_SIZE_GROW)) != DMERR_OK) 319 if ((res = dmGrowBufAlloc(dst, BUF_SIZE_INITIAL, BUF_SIZE_GROW)) != DMERR_OK)
343 return res; 320 return res;
389 366
390 return TRUE; 367 return TRUE;
391 } 368 }
392 369
393 370
394 static int dmEncodeGenericRLE(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd, 371 int dmEncodeGenericRLE(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd,
395 const Uint8 rleMarker, const Uint8 rleMinCount, const Uint8 rleMaxCount, const int rleType) 372 const Uint8 rleMarker, const Uint8 rleMinCount, const Uint8 rleMaxCount, const int rleType)
396 { 373 {
397 int res; 374 int res;
398 375
399 // Perform RLE encoding 376 // Perform RLE encoding
424 err: 401 err:
425 return res; 402 return res;
426 } 403 }
427 404
428 405
429 static int dmEncodeGenericRLEAlloc(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd, 406 int dmEncodeGenericRLEAlloc(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd,
430 const Uint8 rleMarker, const Uint8 rleMinCount, const Uint8 rleMaxCount, const int rleType) 407 const Uint8 rleMarker, const Uint8 rleMinCount, const Uint8 rleMaxCount, const int rleType)
431 { 408 {
432 int res; 409 int res;
433 if ((res = dmGrowBufAlloc(dst, BUF_SIZE_INITIAL, BUF_SIZE_GROW)) != DMERR_OK) 410 if ((res = dmGrowBufAlloc(dst, BUF_SIZE_INITIAL, BUF_SIZE_GROW)) != DMERR_OK)
434 return res; 411 return res;
435 412
436 return dmEncodeGenericRLE(dst, src, srcEnd, rleMarker, rleMinCount, rleMaxCount, rleType); 413 return dmEncodeGenericRLE(dst, src, srcEnd, rleMarker, rleMinCount, rleMaxCount, rleType);
437 } 414 }
438
439
440 static inline Uint8 dmC64GetGenericSCPixel(
441 const DMC64Image *img, const int bmoffs, const int scroffs,
442 const int vshift, const int vbank, const int vbitmap, const int cbank)
443 {
444 (void) cbank;
445 if ((img->bitmap[vbitmap][bmoffs] >> vshift) & 1)
446 return img->screen[vbank][scroffs] >> 4;
447 else
448 return img->screen[vbank][scroffs] & 15;
449 }
450
451
452 static inline Uint8 dmC64GetGenericMCPixel(
453 const DMC64Image *img, const int bmoffs, const int scroffs,
454 const int vshift, const int vbank, const int vbitmap, const int cbank)
455 {
456 switch ((img->bitmap[vbitmap][bmoffs] >> vshift) & 3)
457 {
458 case 0: return img->bgcolor; break;
459 case 1: return img->screen[vbank][scroffs] >> 4; break;
460 case 2: return img->screen[vbank][scroffs] & 15; break;
461 default: return img->color[cbank][scroffs] & 15; break;
462 }
463 }
464
465
466 static inline Uint8 fmtGetGenericSCPixel(
467 const DMC64Image *img, const int bmoffs, const int scroffs,
468 const int vshift, const int vbitmap, const int raster)
469 {
470 (void) raster;
471 return dmC64GetGenericSCPixel(img, bmoffs, scroffs, vshift, 0, vbitmap, 0);
472 }
473
474
475 static inline Uint8 fmtGetGenericMCPixel(
476 const DMC64Image *img, const int bmoffs, const int scroffs,
477 const int vshift, const int vbitmap, const int raster)
478 {
479 (void) raster;
480 return dmC64GetGenericMCPixel(img, bmoffs, scroffs, vshift, 0, vbitmap, 0);
481 }
482
483
484 static int fmtProbeDrazPaint20Packed(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
485 {
486 const char *ident = (const char *) buf + 2;
487
488 if (len > 22 &&
489 dmCompareAddr16(buf, 0, fmt->addr) &&
490 strncmp(ident, "DRAZPAINT ", 10) == 0 &&
491 ident[11] == '.' && (
492 (ident[10] == '1' && ident[12] == '4') ||
493 (ident[10] == '2' && ident[12] == '0')
494 ))
495 return DM_PROBE_SCORE_MAX;
496
497 return DM_PROBE_SCORE_FALSE;
498 }
499
500
501 static int fmtDecodeDrazPaintPacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
502 {
503 int res;
504 DMGrowBuf mem;
505
506 if ((res = dmDecodeGenericRLEAlloc(&mem, buf + 0x0e, buf + len, *(buf + 0x0d), 0, 0, DM_RLE_MARKER)) != DMERR_OK)
507 goto out;
508
509 res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt);
510
511 out:
512 dmGrowBufFree(&mem);
513 return res;
514 }
515
516
517 static int fmtEncodeDrazPaintPacked(DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt)
518 {
519 int res;
520 DMGrowBuf tmp;
521 Uint8 rleMarker;
522 const char *magicID = (fmt->type & D64_FMT_ILACE) ? "DRAZLACE! 1.0" : "DRAZPAINT 2.0";
523
524 // Encode the data to temp buffer
525 if ((res = dmC64EncodeGenericBMP(TRUE, &tmp, img, fmt)) != DMERR_OK)
526 goto out;
527
528 // Analyze the data ..
529 rleMarker = 0xff;
530
531 // Add the header bits
532 if (!dmGrowBufPut(buf, magicID, strlen(magicID)) ||
533 !dmGrowBufPutU8(buf, rleMarker))
534 {
535 res = DMERR_MALLOC;
536 goto out;
537 }
538
539 // And now RLE compress the data to the existing buffer
540 res = dmEncodeGenericRLE(buf, tmp.data, tmp.data + tmp.len,
541 rleMarker, 3, 255, DM_RLE_MARKER);
542
543 out:
544 dmGrowBufFree(&tmp);
545 return res;
546 }
547
548
549 static int fmtProbeDrazLace10Packed(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
550 {
551 if (len > 22 &&
552 dmCompareAddr16(buf, 0, fmt->addr) &&
553 strncmp((const char *) (buf + 2), "DRAZLACE! 1.0", 13) == 0)
554 return DM_PROBE_SCORE_MAX;
555
556 return DM_PROBE_SCORE_FALSE;
557 }
558
559
560 static BOOL fmtDrazLaceSetLaceType(DMC64Image *img, const DMC64EncDecOp *op,
561 const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
562 {
563 (void) len;
564 (void) fmt;
565 img->laceType = buf[op->offs] ? D64_ILACE_RES : D64_ILACE_COLOR;
566 return TRUE;
567 }
568
569
570 static int fmtProbeGunPaint(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
571 {
572 if (len > 0x400 &&
573 dmCompareAddr16(buf, 0, fmt->addr) &&
574 strncmp((const char *) (buf + 0x3ea), "GUNPAINT (JZ) ", 14) == 0)
575 return DM_PROBE_SCORE_MAX;
576
577 return DM_PROBE_SCORE_FALSE;
578 }
579
580
581 static int fmtProbeAmicaPaintPacked(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
582 {
583 size_t i, n;
584
585 if (len < 2048 || !dmCompareAddr16(buf, 0, fmt->addr))
586 return DM_PROBE_SCORE_FALSE;
587
588 // Interpaint Hi-Res gives a false positive
589 // as do some GunPaint images ..
590 if (len == 9002 || fmtProbeGunPaint(buf, len, fmt) > DM_PROBE_SCORE_GOOD)
591 return DM_PROBE_SCORE_FALSE;
592
593 for (n = 0, i = 2; i < len; i++)
594 if (buf[i] == 0xC2) n++;
595
596 if (n > 50)
597 return DM_PROBE_SCORE_GOOD;
598 if (n > 25)
599 return DM_PROBE_SCORE_AVG;
600 if (n > 10)
601 return DM_PROBE_SCORE_MAYBE;
602
603 return DM_PROBE_SCORE_FALSE;
604 }
605
606
607 static int fmtDecodeAmicaPaintPacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
608 {
609 int res;
610 DMGrowBuf mem, tmp;
611
612 // Amica Paint apparently is broken and stores one byte less than it should
613 // so we need to do some crappy buffer expansion here ..
614 if ((res = dmGrowBufAlloc(&tmp, len + 4, 4)) != DMERR_OK)
615 return res;
616
617 tmp.len = len;
618 memcpy(tmp.data, buf, len);
619 tmp.data[tmp.len++] = 0;
620
621 // Now do an RLE decode on the enlarged buffer
622 if ((res = dmDecodeGenericRLE(&mem, tmp.data, tmp.data + tmp.len, 0xC2, 0, 0, DM_RLE_MARKER)) != DMERR_OK)
623 goto out;
624
625 // And finally decode to bitmap struct
626 res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt);
627
628 out:
629 dmGrowBufFree(&tmp);
630 dmGrowBufFree(&mem);
631 return res;
632 }
633
634
635 static int fmtProbeFLIDesigner(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
636 {
637 if (len == fmt->size &&
638 (dmCompareAddr16(buf, 0, 0x3c00) || dmCompareAddr16(buf, 0, 0x3ff0)))
639 return DM_PROBE_SCORE_MAX;
640
641 return DM_PROBE_SCORE_FALSE;
642 }
643
644
645 static BOOL fmtTruePaintSetLaceType(DMC64Image *img, const DMC64EncDecOp *op,
646 const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
647 {
648 (void) op;
649 (void) buf;
650 (void) len;
651 (void) fmt;
652 img->laceType = D64_ILACE_RES;
653 return TRUE;
654 }
655
656
657 static Uint8 fmtGetPixelTruePaint(
658 const DMC64Image *img, const int bmoffs, const int scroffs,
659 const int vshift, const int vbitmap, const int raster)
660 {
661 (void) raster;
662 return dmC64GetGenericMCPixel(img, bmoffs, scroffs, vshift, 0, vbitmap, 0);
663 }
664
665
666 #define XX2_MIN_SIZE 4000
667
668 static int fmtProbeFormatXX2(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
669 {
670 if (len >= XX2_MIN_SIZE && len <= XX2_MIN_SIZE + 8 &&
671 dmCompareAddr16(buf, 0, fmt->addr))
672 return DM_PROBE_SCORE_MAYBE;
673
674 return DM_PROBE_SCORE_FALSE;
675 }
676
677
678 static int fmtDecodeFormatXX2(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
679 {
680 int res;
681
682 // If there is only data for less than XX2_MIN_SIZE bytes,
683 // allocate a buffer of that size and copy data there.
684 // Otherwise allocate len bytes.
685 size_t nlen = len < XX2_MIN_SIZE ? XX2_MIN_SIZE : len;
686 Uint8 *mem = dmMalloc0(nlen);
687 if (mem == NULL)
688 return DMERR_MALLOC;
689
690 memcpy(mem, buf, len);
691 res = dmC64DecodeGenericBMP(img, mem, nlen, fmt);
692
693 dmFree(mem);
694 return res;
695 }
696
697
698 #define FUNPAINT2_HEADER_SIZE (0x10)
699 static const char *fmtFunPaint2MagicID = "FUNPAINT (MT) ";
700
701
702 static BOOL fmtProbeFunPaint2Header(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
703 {
704 return
705 len > 30 &&
706 dmCompareAddr16(buf, 0, fmt->addr) &&
707 strncmp((const char *) (buf + 2), fmtFunPaint2MagicID, strlen(fmtFunPaint2MagicID)) == 0;
708 }
709
710
711 static int fmtProbeFunPaint2Unpacked(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
712 {
713 if (fmtProbeFunPaint2Header(buf, len, fmt) &&
714 buf[2 + 14] == 0)
715 return DM_PROBE_SCORE_MAX;
716 else
717 return DM_PROBE_SCORE_FALSE;
718 }
719
720
721 static int fmtProbeFunPaint2Packed(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
722 {
723 if (fmtProbeFunPaint2Header(buf, len, fmt) &&
724 buf[2 + 14] != 0)
725 return DM_PROBE_SCORE_MAX;
726 else
727 return DM_PROBE_SCORE_FALSE;
728 }
729
730
731 static int fmtDecodeFunPaint2Unpacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
732 {
733 return dmC64DecodeGenericBMP(img, buf + FUNPAINT2_HEADER_SIZE, len - FUNPAINT2_HEADER_SIZE, fmt);
734 }
735
736
737 static int fmtDecodeFunPaint2Packed(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt)
738 {
739 int res;
740 DMGrowBuf mem;
741 dmGrowBufInit(&mem);
742
743 if ((res = dmDecodeGenericRLE(&mem, buf + FUNPAINT2_HEADER_SIZE, buf + len, *(buf + 15), 0, 0, DM_RLE_MARKER)) != DMERR_OK)
744 goto out;
745
746 res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt);
747
748 out:
749 dmGrowBufFree(&mem);
750 return res;
751 }
752
753
754 static Uint8 fmtGetPixelFunPaint2(
755 const DMC64Image *img, const int bmoffs, const int scroffs,
756 const int vshift, const int vbitmap, const int raster)
757 {
758 const int vbank = (raster & 7) + (vbitmap * 8);
759 int vr, vb;
760 if (raster < 100)
761 {
762 vb = 0;
763 vr = raster;
764 }
765 else
766 {
767 vb = 0;
768 vr = raster - 100;
769 }
770
771 switch ((img->bitmap[vbitmap][bmoffs] >> vshift) & 3)
772 {
773 case 0: return img->extraData[vb][vr] & 15; break;
774 case 1: return img->screen[vbank][scroffs] >> 4; break;
775 case 2: return img->screen[vbank][scroffs] & 15; break;
776 default: return img->color[0][scroffs] & 15; break;
777 }
778 }
779
780
781 static Uint8 fmtGetPixelGunPaint(
782 const DMC64Image *img, const int bmoffs, const int scroffs,
783 const int vshift, const int vbitmap, const int raster)
784 {
785 const int vbank = (raster & 7);// + (vbitmap * 8);
786 int vr, vb;
787 if (raster < 177)
788 {
789 vb = 0;
790 vr = raster;
791 }
792 else
793 {
794 vb = 0;
795 vr = raster - 177;
796 }
797
798 switch ((img->bitmap[vbitmap][bmoffs] >> vshift) & 3)
799 {
800 case 0: return img->extraData[vb][vr] & 15; break;
801 case 1: return img->screen[vbank][scroffs] >> 4; break;
802 case 2: return img->screen[vbank][scroffs] & 15; break;
803 default: return img->color[0][scroffs] & 15; break;
804 }
805 }
806
807
808 static Uint8 fmtGetPixelBMFLI(
809 const DMC64Image *img, const int bmoffs, const int scroffs,
810 const int vshift, const int vbitmap, const int raster)
811 {
812 const int vbank = raster & 7;
813 switch ((img->bitmap[vbitmap][bmoffs] >> vshift) & 3)
814 {
815 case 0: return img->extraData[0][raster]; break;
816 case 1: return img->screen[vbank][scroffs] >> 4; break;
817 case 2: return img->screen[vbank][scroffs] & 15; break;
818 default: return img->color[0][scroffs] & 15; break;
819 }
820 }
821
822
823 static Uint8 fmtGetPixelFLIDesigner(
824 const DMC64Image *img, const int bmoffs, const int scroffs,
825 const int vshift, const int vbitmap, const int raster)
826 {
827 return dmC64GetGenericMCPixel(img, bmoffs, scroffs, vshift, raster & 7, vbitmap, 0);
828 }
829
830
831 static Uint8 fmtGetPixelCHFLI(
832 const DMC64Image *img, const int bmoffs, const int scroffs,
833 const int vshift, const int vbitmap, const int raster)
834 {
835 const int vbank = raster & 7;
836
837 if ((img->bitmap[vbitmap][bmoffs] >> vshift) & 1)
838 return img->screen[vbank][scroffs] >> 4;
839 else
840 return img->screen[vbank][scroffs] & 15;
841 }
842
843
844 static int fmtEncodeStub(DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt)
845 {
846 (void) buf;
847 (void) img;
848 (void) fmt;
849
850 return dmError(DMERR_NOT_SUPPORTED,
851 "Encoding of '%s' format not supported.\n",
852 fmt->name);
853 }
854
855
856 //
857 // Array with data for supported formats
858 //
859 #define DEF_SCREEN_RAM(start, oindex, bindex, osize) { DT_SCREEN_RAM, (start) + ((osize) * (oindex)), (bindex), 0, NULL, NULL }
860 #define DEF_SCREEN_RAMS_8(start, sindex, osize) \
861 DEF_SCREEN_RAM((start), 0, (sindex + 0), (osize)), \
862 DEF_SCREEN_RAM((start), 1, (sindex + 1), (osize)), \
863 DEF_SCREEN_RAM((start), 2, (sindex + 2), (osize)), \
864 DEF_SCREEN_RAM((start), 3, (sindex + 3), (osize)), \
865 DEF_SCREEN_RAM((start), 4, (sindex + 4), (osize)), \
866 DEF_SCREEN_RAM((start), 5, (sindex + 5), (osize)), \
867 DEF_SCREEN_RAM((start), 6, (sindex + 6), (osize)), \
868 DEF_SCREEN_RAM((start), 7, (sindex + 7), (osize)),
869
870
871 const DMC64ImageFormat dmC64ImageFormats[] =
872 {
873 {
874 D64_FMT_MC, "d2p", "DrazPaint 1.4/2.0 (packed)", 0x5800, 0,
875 C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
876 C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
877 fmtProbeDrazPaint20Packed,
878 fmtDecodeDrazPaintPacked, fmtEncodeDrazPaintPacked,
879 NULL, NULL,
880 NULL,
881 {
882 { DT_COLOR_RAM, 0x0000, 0, 0, NULL, NULL },
883 { DT_BITMAP, 0x0800, 0, 0, NULL, NULL },
884 { DT_SCREEN_RAM, 0x0400, 0, 0, NULL, NULL },
885 { DT_COLOR_REG, 0x2740, 0, DC_BGCOL, NULL, NULL },
886 { DT_LAST, 0, 0, 0, NULL, NULL },
887 }
888 },
889
890 {
891 D64_FMT_MC, "drp", "DrazPaint (unpacked)", 0x5800, 10051,
892 C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
893 C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
894 NULL,
895 NULL, NULL,
896 NULL, NULL,
897 NULL,
898 {
899 { DT_COLOR_RAM, 0x0000, 0, 0, NULL, NULL },
900 { DT_BITMAP, 0x0800, 0, 0, NULL, NULL },
901 { DT_SCREEN_RAM, 0x0400, 0, 0, NULL, NULL },
902 { DT_COLOR_REG, 0x2740, 0, DC_BGCOL, NULL, NULL },
903 { DT_LAST, 0, 0, 0, NULL, NULL },
904 }
905 },
906
907 {
908 D64_FMT_MC | D64_FMT_ILACE, "dlp", "DrazLace 1.0 (packed)", 0x5800, 0,
909 C64_SCR_WIDTH , C64_SCR_HEIGHT,
910 C64_SCR_CH_WIDTH, C64_SCR_CH_HEIGHT,
911 fmtProbeDrazLace10Packed,
912 fmtDecodeDrazPaintPacked, fmtEncodeDrazPaintPacked,
913 NULL, NULL,
914 NULL,
915 {
916 { DT_COLOR_RAM, 0x0000, 0, 0, NULL, NULL },
917 { DT_BITMAP, 0x0800, 0, 0, NULL, NULL },
918 { DT_SCREEN_RAM, 0x0400, 0, 0, NULL, NULL },
919 { DT_COLOR_REG, 0x2740, 0, DC_BGCOL, NULL, NULL },
920 { DT_BITMAP, 0x2800, 1, 0, NULL, NULL },
921 { DT_DEC_FUNCTION, 0x2742, 0, 1, fmtDrazLaceSetLaceType, NULL },
922 { DT_LAST, 0, 0, 0, NULL, NULL },
923 }
924 },
925
926 {
927 D64_FMT_MC | D64_FMT_ILACE, "drl", "DrazLace 1.0 (unpacked)", 0x5800, 18242,
928 C64_SCR_WIDTH , C64_SCR_HEIGHT,
929 C64_SCR_CH_WIDTH, C64_SCR_CH_HEIGHT,
930 NULL,
931 NULL, NULL,
932 NULL, NULL,
933 NULL,
934 {
935 { DT_COLOR_RAM, 0x0000, 0, 0, NULL, NULL },
936 { DT_BITMAP, 0x0800, 0, 0, NULL, NULL },
937 { DT_SCREEN_RAM, 0x0400, 0, 0, NULL, NULL },
938 { DT_COLOR_REG, 0x2740, 0, DC_BGCOL, NULL, NULL },
939 { DT_BITMAP, 0x2800, 1, 0, NULL, NULL },
940 { DT_DEC_FUNCTION, 0x2742, 0, 1, fmtDrazLaceSetLaceType, NULL },
941 { DT_LAST, 0, 0, 0, NULL, NULL },
942 }
943 },
944
945 {
946 D64_FMT_MC | D64_FMT_ILACE, "mci", "Truepaint (unpacked)", 0x9c00, 19434,
947 C64_SCR_WIDTH , C64_SCR_HEIGHT,
948 C64_SCR_CH_WIDTH, C64_SCR_CH_HEIGHT,
949 NULL,
950 NULL, NULL,
951 NULL, NULL,
952 fmtGetPixelTruePaint,
953 {
954 { DT_SCREEN_RAM, 0x0000, 0, 0, NULL, NULL },
955 { DT_COLOR_REG, 0x03e8, 0, DC_BGCOL, NULL, NULL },
956 { DT_BITMAP, 0x0400, 0, 0, NULL, NULL },
957 { DT_BITMAP, 0x2400, 1, 0, NULL, NULL },
958 { DT_SCREEN_RAM, 0x4400, 1, 0, NULL, NULL },
959 { DT_COLOR_RAM, 0x4800, 0, 0, NULL, NULL },
960 { DT_DEC_FUNCTION, 0x0000, 0, 0, fmtTruePaintSetLaceType, NULL },
961 { DT_LAST, 0, 0, 0, NULL, NULL },
962 }
963 },
964
965 {
966 D64_FMT_MC, "kla", "Koala Paint (unpacked)", 0x6000, 10003,
967 C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
968 C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
969 NULL,
970 NULL, NULL,
971 NULL, NULL,
972 NULL,
973 {
974 { DT_BITMAP, 0x0000, 0, 0, NULL, NULL },
975 { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL },
976 { DT_COLOR_RAM, 0x2328, 0, 0, NULL, NULL },
977 { DT_COLOR_REG, 0x2710, 0, DC_BGCOL, NULL, NULL },
978 { DT_LAST, 0, 0, 0, NULL, NULL },
979 }
980 },
981
982 {
983 D64_FMT_MC, "ocp", "Advanced Art Studio (unpacked)", 0x2000, 10018,
984 C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
985 C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
986 NULL,
987 NULL, NULL,
988 NULL, NULL,
989 NULL,
990 {
991 { DT_BITMAP, 0x0000, 0, 0, NULL, NULL },
992 { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL },
993 { DT_COLOR_RAM, 0x2338, 0, 0, NULL, NULL },
994 { DT_COLOR_REG, 0x2329, 0, DC_BGCOL, NULL, NULL },
995 { DT_LAST, 0, 0, 0, NULL, NULL },
996 }
997 },
998
999 {
1000 D64_FMT_MC, "ami", "Amica Paint (packed)", 0x4000, 0,
1001 C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
1002 C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
1003 fmtProbeAmicaPaintPacked,
1004 fmtDecodeAmicaPaintPacked, fmtEncodeStub,
1005 NULL, NULL,
1006 NULL,
1007 {
1008 { DT_COLOR_RAM, 0x2328, 0, 0, NULL, NULL },
1009 { DT_BITMAP, 0x0000, 0, 0, NULL, NULL },
1010 { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL },
1011 { DT_COLOR_REG, 0x2710, 0, DC_BGCOL, NULL, NULL },
1012 { DT_LAST, 0, 0, 0, NULL, NULL },
1013 }
1014 },
1015
1016 {
1017 D64_FMT_MC, "rpm", "Run Paint (unpacked)", 0x6000, 10006,
1018 C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
1019 C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
1020 NULL,
1021 NULL, NULL,
1022 NULL, NULL,
1023 NULL,
1024 {
1025 { DT_COLOR_RAM, 0x2328, 0, 0, NULL, NULL },
1026 { DT_BITMAP, 0x0000, 0, 0, NULL, NULL },
1027 { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL },
1028 { DT_COLOR_REG, 0x2710, 0, DC_BGCOL, NULL, NULL },
1029 { DT_LAST, 0, 0, 0, NULL, NULL },
1030 }
1031 },
1032
1033 {
1034 D64_FMT_HIRES, "art", "Art Studio (unpacked)", 0x2000, 9009,
1035 C64_SCR_WIDTH , C64_SCR_HEIGHT,
1036 C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
1037 NULL,
1038 NULL, NULL,
1039 NULL, NULL,
1040 NULL,
1041 {
1042 { DT_BITMAP, 0x0000, 0, 0, NULL, NULL },
1043 { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL },
1044 { DT_LAST, 0, 0, 0, NULL, NULL },
1045 }
1046 },
1047
1048 {
1049 D64_FMT_HIRES, "iph", "Interpaint (unpacked)", 0x4000, 9002,
1050 C64_SCR_WIDTH , C64_SCR_HEIGHT,
1051 C64_SCR_CH_WIDTH, C64_SCR_CH_HEIGHT,
1052 NULL,
1053 NULL, NULL,
1054 NULL, NULL,
1055 NULL,
1056 {
1057 { DT_BITMAP, 0x0000, 0, 0, NULL, NULL },
1058 { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL },
1059 { DT_LAST, 0, 0, 0, NULL, NULL },
1060 }
1061 },
1062
1063 {
1064 D64_FMT_MC, "ipc", "Interpaint MC (unpacked)", 0x4000, 10003,
1065 C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
1066 C64_SCR_CH_WIDTH, C64_SCR_CH_HEIGHT,
1067 NULL,
1068 NULL, NULL,
1069 NULL, NULL,
1070 NULL,
1071 {
1072 { DT_BITMAP, 0x0000, 0, 0, NULL, NULL },
1073 { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL },
1074 { DT_COLOR_RAM, 0x2328, 0, 0, NULL, NULL },
1075 { DT_COLOR_REG, 0x2710, 0, DC_BGCOL, NULL, NULL },
1076 { DT_LAST, 0, 0, 0, NULL, NULL },
1077 }
1078 },
1079
1080 {
1081 D64_FMT_HIRES, "dd", "Doodle (unpacked)", 0x1c00, 9218,
1082 C64_SCR_WIDTH , C64_SCR_HEIGHT,
1083 C64_SCR_CH_WIDTH, C64_SCR_CH_HEIGHT,
1084 NULL,
1085 NULL, NULL,
1086 NULL, NULL,
1087 NULL,
1088 {
1089 { DT_SCREEN_RAM, 0x0000, 0, 0, NULL, NULL },
1090 { DT_BITMAP, 0x0400, 0, 0, NULL, NULL },
1091 { DT_LAST, 0, 0, 0, NULL, NULL },
1092 }
1093 },
1094
1095 {
1096 D64_FMT_MC | D64_FMT_FLI, "bml", "Blackmail FLI (unpacked)", 0x3b00, 17474,
1097 C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
1098 C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
1099 NULL,
1100 NULL, NULL,
1101 NULL, NULL,
1102 fmtGetPixelBMFLI,
1103 {
1104 { DT_EXTRA_DATA, 0x0000, 0, 200, NULL, NULL },
1105 { DT_COLOR_RAM, 0x0100, 0, 0, NULL, NULL },
1106 DEF_SCREEN_RAMS_8( 0x0500, 0, 0x400)
1107 { DT_BITMAP, 0x2500, 0, 0, NULL, NULL },
1108 { DT_LAST, 0, 0, 0, NULL, NULL },
1109 }
1110 },
1111
1112 {
1113 D64_FMT_MC | D64_FMT_FLI, "fli", "FLI Designer (unpacked)", 0, 17409,
1114 C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
1115 C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
1116 fmtProbeFLIDesigner,
1117 NULL, NULL,
1118 NULL, NULL,
1119 fmtGetPixelFLIDesigner,
1120 {
1121 { DT_COLOR_RAM, 0x0000, 0, 0, NULL, NULL },
1122 DEF_SCREEN_RAMS_8( 0x0400, 0, 0x400)
1123 { DT_BITMAP, 0x2400, 0, 0, NULL, NULL },
1124 { DT_LAST, 0, 0, 0, NULL, NULL },
1125 }
1126 },
1127
1128 {
1129 D64_FMT_MC, "xx1", "Unknown $2000 format (unpacked)", 0x2000, 10242,
1130 C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
1131 C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
1132 NULL,
1133 NULL, NULL,
1134 NULL, NULL,
1135 NULL,
1136 {
1137 { DT_BITMAP, 0x0000, 0, 0, NULL, NULL },
1138 { DT_SCREEN_RAM, 0x2000, 0, 0, NULL, NULL },
1139 { DT_COLOR_RAM, 0x2400, 0, 0, NULL, NULL },
1140 { DT_COLOR_SET, 0x00 , 0, DC_BGCOL, NULL, NULL },
1141 { DT_LAST, 0, 0, 0, NULL, NULL },
1142 }
1143 },
1144
1145 #define XX2_WIDTH_CH 40
1146 #define XX2_HEIGHT_CH 10
1147 #define XX2_SIZE (XX2_WIDTH_CH * XX2_HEIGHT_CH)
1148 #define XX2_BSIZE (XX2_SIZE * 8)
1149
1150 {
1151 D64_FMT_MC, "xx2", "Unknown $2000 format (unpacked)", 0x2000, 0,
1152 XX2_WIDTH_CH * 4, XX2_HEIGHT_CH * 8,
1153 XX2_WIDTH_CH , XX2_HEIGHT_CH,
1154 fmtProbeFormatXX2,
1155 fmtDecodeFormatXX2, NULL,
1156 NULL, NULL,
1157 NULL,
1158 {
1159 { DT_BITMAP, 0x0000, 0, XX2_BSIZE, NULL, NULL },
1160 { DT_COLOR_RAM, XX2_BSIZE + XX2_SIZE, 0, XX2_SIZE, NULL, NULL },
1161 { DT_SCREEN_RAM, XX2_BSIZE, 0, XX2_SIZE, NULL, NULL },
1162 { DT_COLOR_SET, 11, 0, DC_BGCOL, NULL, NULL },
1163 { DT_LAST, 0, 0, 0, NULL, NULL },
1164 }
1165 },
1166
1167 {
1168 D64_FMT_MC | D64_FMT_FLI | D64_FMT_ILACE, "fp2", "FunPaint II (unpacked)", 0x3ff0, 33694,
1169 C64_SCR_WIDTH, C64_SCR_HEIGHT,
1170 C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
1171 fmtProbeFunPaint2Unpacked,
1172 fmtDecodeFunPaint2Unpacked, fmtEncodeStub,
1173 NULL, NULL,
1174 fmtGetPixelFunPaint2,
1175 {
1176 DEF_SCREEN_RAMS_8( 0x0000, 0, 0x400)
1177 { DT_BITMAP, 0x2000, 0, 0, NULL, NULL },
1178 { DT_EXTRA_DATA, 0x3f40, 0, 100, NULL, NULL },
1179 { DT_COLOR_RAM, 0x4000, 0, 0, NULL, NULL },
1180 DEF_SCREEN_RAMS_8( 0x43e8, 8, 0x400)
1181 { DT_BITMAP, 0x63e8, 1, 0, NULL, NULL },
1182 { DT_EXTRA_DATA, 0x8328, 1, 100, NULL, NULL },
1183 { DT_LAST, 0, 0, 0, NULL, NULL },
1184 }
1185 },
1186
1187 {
1188 D64_FMT_MC | D64_FMT_FLI | D64_FMT_ILACE, "fp2p", "FunPaint II (packed)", 0x3ff0, 0,
1189 C64_SCR_WIDTH, C64_SCR_HEIGHT,
1190 C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
1191 fmtProbeFunPaint2Packed,
1192 fmtDecodeFunPaint2Packed, fmtEncodeStub,
1193 NULL, NULL,
1194 fmtGetPixelFunPaint2,
1195 {
1196 DEF_SCREEN_RAMS_8( 0x0000, 0, 0x400)
1197 { DT_BITMAP, 0x2000, 0, 0, NULL, NULL },
1198 { DT_EXTRA_DATA, 0x3f40, 0, 100, NULL, NULL },
1199 { DT_COLOR_RAM, 0x4000, 0, 0, NULL, NULL },
1200 DEF_SCREEN_RAMS_8( 0x43e8, 8, 0x400)
1201 { DT_BITMAP, 0x63e8, 1, 0, NULL, NULL },
1202 { DT_EXTRA_DATA, 0x8328, 1, 100, NULL, NULL },
1203 { DT_LAST, 0, 0, 0, NULL, NULL },
1204 }
1205 },
1206
1207 {
1208 D64_FMT_MC | D64_FMT_FLI | D64_FMT_ILACE, "gun", "GunPaint (unpacked)", 0x4000, 0,
1209 C64_SCR_WIDTH, C64_SCR_HEIGHT,
1210 C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
1211 fmtProbeGunPaint,
1212 NULL, NULL,
1213 NULL, NULL,
1214 fmtGetPixelGunPaint,
1215 {
1216 DEF_SCREEN_RAMS_8( 0x0000, 0, 0x400)
1217 { DT_BITMAP, 0x2000, 0, 0, NULL, NULL },
1218 { DT_EXTRA_DATA, 0x3f4f, 0, 177, NULL, NULL },
1219 { DT_COLOR_RAM, 0x4000, 0, 0, NULL, NULL },
1220 DEF_SCREEN_RAMS_8( 0x4400, 8, 0x400)
1221 { DT_BITMAP, 0x6400, 1, 0, NULL, NULL },
1222 { DT_EXTRA_DATA, 0x47e8, 1, 20, NULL, NULL },
1223 { DT_LAST, 0, 0, 0, NULL, NULL },
1224 }
1225 },
1226
1227 {
1228 D64_FMT_HIRES | D64_FMT_FLI, "chi", "Crest Hires FLI Designer (unpacked)", 0x4000, 16386,
1229 C64_SCR_WIDTH, 14 * 8,
1230 C64_SCR_CH_WIDTH , 14,
1231 NULL,
1232 NULL, NULL,
1233 NULL, NULL,
1234 fmtGetPixelCHFLI,
1235 {
1236 { DT_BITMAP, 0x0000, 0, 0, NULL, NULL },
1237 DEF_SCREEN_RAMS_8( 0x2000, 0, 0x400)
1238 { DT_LAST, 0, 0, 0, NULL, NULL },
1239 }
1240 },
1241 };
1242
1243 const int ndmC64ImageFormats = sizeof(dmC64ImageFormats) / sizeof(dmC64ImageFormats[0]);
1244 415
1245 416
1246 // Perform probing of the given data buffer, trying to determine 417 // Perform probing of the given data buffer, trying to determine
1247 // if it contains a supported "C64" image format. Returns the 418 // if it contains a supported "C64" image format. Returns the
1248 // "probe score", see libgfx.h for list of values. If a match 419 // "probe score", see libgfx.h for list of values. If a match