Mercurial > hg > dmlib
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 } |