comparison tools/lib64gfx.c @ 1588:ca087c0cc9c4

Refactor the c64 format memory handling a bit for more flexibility.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 14 May 2018 04:27:53 +0300
parents 3c9e5962eca6
children 3cc7b2aadda3
comparison
equal deleted inserted replaced
1587:e6a228b50bd6 1588:ca087c0cc9c4
98 98
99 return nbanks + 1; 99 return nbanks + 1;
100 } 100 }
101 101
102 102
103 int dmC64MemBlockAlloc(DMC64MemBlock *blk, const size_t size)
104 {
105 if ((blk->data = dmMalloc0(size)) == NULL)
106 return DMERR_MALLOC;
107
108 blk->size = size;
109 return DMERR_OK;
110 }
111
112
113 int dmC64MemBlockCopy(DMC64MemBlock *dst, const DMC64MemBlock *src)
114 {
115 if (src->data != NULL && src->size > 0)
116 {
117 dst->size = src->size;
118 if ((dst->data = dmMalloc(src->size)) == NULL)
119 return DMERR_MALLOC;
120
121 memcpy(dst->data, src->data, src->size);
122 }
123
124 return DMERR_OK;
125 }
126
127
128 void dmC64MemBlockFree(DMC64MemBlock *blk)
129 {
130 if (blk != NULL)
131 {
132 dmFreeR(&blk->data);
133 blk->size = 0;
134 }
135 }
136
137
103 DMC64Image *dmC64ImageAlloc(const DMC64ImageFormat *fmt) 138 DMC64Image *dmC64ImageAlloc(const DMC64ImageFormat *fmt)
104 { 139 {
105 DMC64Image *img = dmMalloc0(sizeof(DMC64Image)); 140 DMC64Image *img = dmMalloc0(sizeof(DMC64Image));
106 141
107 if (img == NULL) 142 if (img == NULL)
113 img->height = fmt->height; 148 img->height = fmt->height;
114 img->chWidth = fmt->chWidth; 149 img->chWidth = fmt->chWidth;
115 img->chHeight = fmt->chHeight; 150 img->chHeight = fmt->chHeight;
116 img->nbanks = dmC64ImageGetNumBanks(fmt); 151 img->nbanks = dmC64ImageGetNumBanks(fmt);
117 152
118 img->screenSize = img->chWidth * img->chHeight;
119 img->bitmapSize = img->screenSize * 8;
120 img->charmemSize = C64_MAX_CHARS * C64_CHR_SIZE;
121
122 // Allocate banks 153 // Allocate banks
123 if ((img->color = dmCalloc(img->nbanks, sizeof(Uint8 *))) == NULL || 154 if ((img->color = dmCalloc(img->nbanks, sizeof(DMC64MemBlock))) == NULL ||
124 (img->bitmap = dmCalloc(img->nbanks, sizeof(Uint8 *))) == NULL || 155 (img->bitmap = dmCalloc(img->nbanks, sizeof(DMC64MemBlock))) == NULL ||
125 (img->screen = dmCalloc(img->nbanks, sizeof(Uint8 *))) == NULL || 156 (img->screen = dmCalloc(img->nbanks, sizeof(DMC64MemBlock))) == NULL ||
126 (img->charmem = dmCalloc(img->nbanks, sizeof(Uint8 *))) == NULL) 157 (img->charData = dmCalloc(img->nbanks, sizeof(DMC64MemBlock))) == NULL)
127 goto err; 158 goto err;
128
129 for (int i = 0; i < img->nbanks; i++)
130 {
131 if ((img->color[i] = dmMalloc0(img->screenSize)) == NULL)
132 goto err;
133
134 if ((img->bitmap[i] = dmMalloc0(img->bitmapSize)) == NULL)
135 goto err;
136
137 if ((img->screen[i] = dmMalloc0(img->screenSize)) == NULL)
138 goto err;
139
140 if ((img->charmem[i] = dmMalloc0(img->charmemSize)) == NULL)
141 goto err;
142 }
143 159
144 return img; 160 return img;
145 161
146 err: 162 err:
147 dmC64ImageFree(img); 163 dmC64ImageFree(img);
154 if (img != NULL) 170 if (img != NULL)
155 { 171 {
156 // Free the allocated areas 172 // Free the allocated areas
157 for (int i = 0; i < img->nbanks; i++) 173 for (int i = 0; i < img->nbanks; i++)
158 { 174 {
159 dmFree(img->color[i]); 175 dmC64MemBlockFree(&img->color[i]);
160 dmFree(img->bitmap[i]); 176 dmC64MemBlockFree(&img->bitmap[i]);
161 dmFree(img->screen[i]); 177 dmC64MemBlockFree(&img->screen[i]);
162 dmFree(img->charmem[i]); 178 dmC64MemBlockFree(&img->charData[i]);
163 } 179 }
164 180
165 // Free the pointers to the areas 181 // Free the pointers to the areas
166 dmFree(img->color); 182 dmFree(img->color);
167 dmFree(img->bitmap); 183 dmFree(img->bitmap);
168 dmFree(img->screen); 184 dmFree(img->screen);
169 dmFree(img->charmem); 185 dmFree(img->charData);
170 186
171 // Extra data .. 187 // Extra data ..
172 for (int i = 0; i < C64_MAX_EXTRA_DATA; i++) 188 for (int i = 0; i < C64_MAX_EXTRA_DATA; i++)
173 dmFree(img->extraData[i]); 189 dmC64MemBlockFree(&img->extraData[i]);
174 190
175 dmMemset(img, 0, sizeof(DMC64Image)); 191 dmMemset(img, 0, sizeof(DMC64Image));
176 dmFree(img); 192 dmFree(img);
177 } 193 }
178 } 194 }
594 // Perform decoding 610 // Perform decoding
595 for (int i = 0; i < D64_MAX_ENCDEC_OPS; i++) 611 for (int i = 0; i < D64_MAX_ENCDEC_OPS; i++)
596 { 612 {
597 const DMC64EncDecOp *op = &fmt->encdecOps[i]; 613 const DMC64EncDecOp *op = &fmt->encdecOps[i];
598 const Uint8 *src; 614 const Uint8 *src;
615 DMC64MemBlock *blk;
616 char *blkname;
599 size_t size; 617 size_t size;
600 618
601 // Check for last operator 619 // Check for last operator
602 if (op->type == DT_LAST) 620 if (op->type == DT_LAST)
603 break; 621 break;
613 "Decode op SIZE out of bounds, op #%d type=%d, offs=%d ($%04x), " 631 "Decode op SIZE out of bounds, op #%d type=%d, offs=%d ($%04x), "
614 "bank=%d, size=%d ($%04x) vs. allocated %d ($%04x)\n", 632 "bank=%d, size=%d ($%04x) vs. allocated %d ($%04x)\n",
615 i, op->type, op->offs, op->offs, op->bank, size, size, op->size, op->size); 633 i, op->type, op->offs, op->offs, op->bank, size, size, op->size, op->size);
616 } 634 }
617 635
618 // Do we need to reallocate some more space? 636 // Is the operation inside the bounds?
619 if (op->offs + size > len + 1) 637 if (op->offs + size > len + 1)
620 { 638 {
621 return dmError(DMERR_INVALID_DATA, 639 return dmError(DMERR_INVALID_DATA,
622 "Decode out of bounds, op #%d type=%d, offs=%d ($%04x), " 640 "Decode DATA out of bounds, op #%d type=%d, offs=%d ($%04x), "
623 "bank=%d, size=%d ($%04x) @ %d ($%04x)\n", 641 "bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
624 i, op->type, op->offs, op->offs, op->bank, size, size, len, len); 642 i, op->type, op->offs, op->offs, op->bank, size, size, len, len);
625 } 643 }
626 644
627 src = buf + op->offs; 645 src = buf + op->offs;
628 646
629 // Perform operation 647 // Perform operation
630 switch (op->type) 648 switch (op->type)
631 { 649 {
632 case DT_COLOR_RAM: memcpy(img->color[op->bank], src, size); break; 650 case DT_COLOR_RAM:
633 case DT_BITMAP_RAM: memcpy(img->bitmap[op->bank], src, size); break; 651 case DT_SCREEN_RAM:
634 case DT_SCREEN_RAM: memcpy(img->screen[op->bank], src, size); break; 652 case DT_BITMAP_RAM:
635 case DT_CHAR_DATA: memcpy(img->charmem[op->bank], src, size); break; 653 case DT_CHAR_DATA:
636 case DT_EXTRA_DATA: 654 case DT_EXTRA_DATA:
637 if (img->extraData[op->bank] != NULL) 655 switch (op->type)
638 { 656 {
639 return dmError(DMERR_INTERNAL, 657 case DT_COLOR_RAM : blk = &img->color[op->bank]; blkname = "Color RAM"; break;
640 "Extra data block already allocated and used! " 658 case DT_SCREEN_RAM : blk = &img->screen[op->bank]; blkname = "Screen RAM"; break;
659 case DT_BITMAP_RAM : blk = &img->bitmap[op->bank]; blkname = "Bitmap RAM"; break;
660 case DT_CHAR_DATA : blk = &img->charData[op->bank]; blkname = "Character data"; break;
661 case DT_EXTRA_DATA : blk = &img->extraData[op->bank]; blkname = "Extra data"; break;
662 }
663 if ((dmC64MemBlockAlloc(blk, size)) != DMERR_OK)
664 {
665 return dmError(DMERR_MALLOC,
666 "Could not allocate '%s' block! "
641 "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", 667 "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
642 i, op->offs, op->offs, op->bank, size, size, len, len); 668 blkname, i, op->offs, op->offs, op->bank, size, size, len, len);
643 } 669 }
644 if ((img->extraData[op->bank] = dmMalloc0(size)) == NULL) 670 blk->size = size;
645 { 671 memcpy(blk->data, src, size);
646 return dmError(DMERR_MALLOC,
647 "Could not allocate extradata block! "
648 "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
649 i, op->offs, op->offs, op->bank, size, size, len, len);
650 }
651 img->extraDataSizes[op->bank] = size;
652 memcpy(img->extraData[op->bank], src, size);
653 break; 672 break;
654 673
655 case DT_COLOR_REG: 674 case DT_COLOR_REG:
656 switch (op->size) 675 switch (op->size)
657 { 676 {
694 713
695 case D64_CHCFG_LINEAR: 714 case D64_CHCFG_LINEAR:
696 { 715 {
697 for (int bank = 0; bank < img->nbanks; bank++) 716 for (int bank = 0; bank < img->nbanks; bank++)
698 for (int offs = 0; offs < fmt->chHeight * fmt->chWidth; offs++) 717 for (int offs = 0; offs < fmt->chHeight * fmt->chWidth; offs++)
699 img->screen[bank][offs] = offs & 0xff; 718 img->screen[bank].data[offs] = offs & 0xff;
700 } 719 }
701 break; 720 break;
702 721
703 default: 722 default:
704 return dmError(DMERR_INTERNAL, 723 return dmError(DMERR_INTERNAL,
752 // Perform encoding 771 // Perform encoding
753 for (int i = 0; i < D64_MAX_ENCDEC_OPS; i++) 772 for (int i = 0; i < D64_MAX_ENCDEC_OPS; i++)
754 { 773 {
755 const DMC64EncDecOp *op = &fmt->encdecOps[i]; 774 const DMC64EncDecOp *op = &fmt->encdecOps[i];
756 size_t size, chksize; 775 size_t size, chksize;
776 const DMC64MemBlock *blk;
777 char *blkname;
757 778
758 // Check for last operator 779 // Check for last operator
759 if (op->type == DT_LAST) 780 if (op->type == DT_LAST)
760 break; 781 break;
761 782
788 809
789 // Perform operation 810 // Perform operation
790 Uint8 *dst = buf->data + op->offs; 811 Uint8 *dst = buf->data + op->offs;
791 switch (op->type) 812 switch (op->type)
792 { 813 {
793 case DT_COLOR_RAM: memcpy(dst, img->color[op->bank], size); break; 814 case DT_COLOR_RAM:
794 case DT_BITMAP_RAM: memcpy(dst, img->bitmap[op->bank], size); break; 815 case DT_SCREEN_RAM:
795 case DT_SCREEN_RAM: memcpy(dst, img->screen[op->bank], size); break; 816 case DT_BITMAP_RAM:
796 case DT_CHAR_DATA: memcpy(dst, img->charmem[op->bank], size); break; 817 case DT_CHAR_DATA:
797 case DT_EXTRA_DATA: 818 case DT_EXTRA_DATA:
798 if (img->extraData[op->bank] == NULL) 819 switch (op->type)
820 {
821 case DT_COLOR_RAM : blk = &img->color[op->bank]; blkname = "Color RAM"; break;
822 case DT_SCREEN_RAM : blk = &img->screen[op->bank]; blkname = "Screen RAM"; break;
823 case DT_BITMAP_RAM : blk = &img->bitmap[op->bank]; blkname = "Bitmap RAM"; break;
824 case DT_CHAR_DATA : blk = &img->charData[op->bank]; blkname = "Character data"; break;
825 case DT_EXTRA_DATA : blk = &img->extraData[op->bank]; blkname = "Extra data"; break;
826 }
827 if (blk->data == NULL)
799 { 828 {
800 res = dmError(DMERR_NULLPTR, 829 res = dmError(DMERR_NULLPTR,
801 "DT_EXTRA_DATA block is NULL in " 830 "'%s' block is NULL in "
802 "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", 831 "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
803 i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len); 832 blkname, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len);
804 goto err; 833 goto err;
805 } 834 }
806 if (size > img->extraDataSizes[op->bank]) 835 if (size > blk->size)
807 { 836 {
808 res = dmError(DMERR_INTERNAL, 837 res = dmError(DMERR_INTERNAL,
809 "DT_EXTRA_DATA size mismatch %d <> %d in " 838 "'%s' size mismatch %d <> %d in "
810 "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", 839 "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n",
811 op->size, img->extraDataSizes[op->bank], i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len); 840 blkname, op->size, blk->size, i, op->offs, op->offs, op->bank, size, size, buf->len, buf->len);
812 goto err; 841 goto err;
813 } 842 }
814 memcpy(dst, img->extraData[op->bank], size); 843 memcpy(dst, blk->data, size);
815 break; 844 break;
816 845
817 case DT_COLOR_REG: 846 case DT_COLOR_REG:
818 switch (op->size) 847 switch (op->size)
819 { 848 {
908 // Hi-res charmap 937 // Hi-res charmap
909 for (xc = 0; xc < rwidth; xc++) 938 for (xc = 0; xc < rwidth; xc++)
910 { 939 {
911 const int x = xc / 8; 940 const int x = xc / 8;
912 const int scroffs = scroffsy + x; 941 const int scroffs = scroffsy + x;
913 const int chr = src->screen[0][scroffs]; 942 const int chr = src->screen[0].data[scroffs];
914 const int v = 7 - (xc & 7); 943 const int v = 7 - (xc & 7);
915 944
916 if ((src->charmem[0][chr * C64_CHR_SIZE + yb] >> v) & 1) 945 if ((src->charData[0].data[chr * C64_CHR_SIZE + yb] >> v) & 1)
917 *d++ = src->color[0][scroffs]; 946 *d++ = src->color[0].data[scroffs];
918 else 947 else
919 *d++ = src->bgcolor; 948 *d++ = src->bgcolor;
920 } 949 }
921 else 950 else
922 // Multicolor variants 951 // Multicolor variants
923 for (xc = 0; xc < rwidth; xc++) 952 for (xc = 0; xc < rwidth; xc++)
924 { 953 {
925 const int x = xc / 4; 954 const int x = xc / 4;
926 const int scroffs = scroffsy + x; 955 const int scroffs = scroffsy + x;
927 const int chr = src->screen[0][scroffs]; 956 const int chr = src->screen[0].data[scroffs];
928 const int col = src->color[0][scroffs] & 15; 957 const int col = src->color[0].data[scroffs] & 15;
929 958
930 if (col & 8) 959 if (col & 8)
931 { 960 {
932 const int v = 6 - ((xc * 2) & 6); 961 const int v = 6 - ((xc * 2) & 6);
933 switch ((src->charmem[0][chr * C64_CHR_SIZE + yb] >> v) & 3) 962 switch ((src->charData[0].data[chr * C64_CHR_SIZE + yb] >> v) & 3)
934 { 963 {
935 case 0: *d++ = src->bgcolor; break; 964 case 0: *d++ = src->bgcolor; break;
936 case 1: *d++ = src->d022; break; 965 case 1: *d++ = src->d022; break;
937 case 2: *d++ = src->d023; break; 966 case 2: *d++ = src->d023; break;
938 case 3: *d++ = col; 967 case 3: *d++ = col;
939 } 968 }
940 } 969 }
941 else 970 else
942 { 971 {
943 const int v = 7 - (xc & 7); 972 const int v = 7 - (xc & 7);
944 if ((src->charmem[0][chr * C64_CHR_SIZE + yb] >> v) & 1) 973 if ((src->charData[0].data[chr * C64_CHR_SIZE + yb] >> v) & 1)
945 *d++ = src->color[0][scroffs]; 974 *d++ = src->color[0].data[scroffs];
946 else 975 else
947 *d++ = src->bgcolor; 976 *d++ = src->bgcolor;
948 } 977 }
949 } 978 }
950 } 979 }