Mercurial > hg > dmlib
changeset 912:70cbbd5b7aea
Moved lib64gfx files under tools, as it's not generic DMLIB module really.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 24 Feb 2015 00:47:39 +0200 |
parents | 602b4aa34293 |
children | 7d1696edf244 |
files | Makefile.gen src/lib64gfx.c src/lib64gfx.h tools/lib64gfx.c tools/lib64gfx.h |
diffstat | 5 files changed, 1091 insertions(+), 1091 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile.gen Mon Feb 23 22:55:32 2015 +0200 +++ b/Makefile.gen Tue Feb 24 00:47:39 2015 +0200 @@ -231,7 +231,7 @@ ### Dependancies ifeq ($(DM_BUILD_TOOLS),yes) -DMLIB_OBJS += libgfx.o lib64gfx.o +DMLIB_OBJS += libgfx.o ifeq ($(DM_USE_STDIO),yes) TOOL_BINARIES+= objlink data2inc gfxconv gentab ifeq ($(SUP_MODLOAD),yes) @@ -485,11 +485,11 @@ @echo " LINK $+" @$(CC) -o $@ $(filter %.o %.a,$+) $(DM_LDFLAGS) -$(TOOL_BINPATH)gfxconv$(EXEEXT): $(OBJPATH)gfxconv.o $(DMLIB_A) +$(TOOL_BINPATH)gfxconv$(EXEEXT): $(OBJPATH)gfxconv.o $(OBJPATH)lib64gfx.o $(DMLIB_A) @echo " LINK $+" @$(CC) -o $@ $(filter %.o %.a,$+) $(DM_LDFLAGS) $(LIBPNG_LDFLAGS) $(ZLIB_LDFLAGS) -$(TOOL_BINPATH)view64$(EXEEXT): $(OBJPATH)view64.o $(DMLIB_A) +$(TOOL_BINPATH)view64$(EXEEXT): $(OBJPATH)view64.o $(OBJPATH)lib64gfx.o $(DMLIB_A) @echo " LINK $+" @$(CC) -o $@ $(filter %.o %.a,$+) $(DM_LDFLAGS) $(LIBPNG_LDFLAGS) $(ZLIB_LDFLAGS) $(SDL_LDFLAGS)
--- a/src/lib64gfx.c Mon Feb 23 22:55:32 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,893 +0,0 @@ -/* - * Functions for reading and converting various restricted - * C64/etc and/or indexed/paletted graphics formats. - * Programmed and designed by Matti 'ccr' Hamalainen - * (C) Copyright 2012 Tecnic Software productions (TNSP) - * - * Please read file 'COPYING' for information on license and distribution. - */ -#include "lib64gfx.h" - -#define BUF_SIZE_INITIAL (16*1024) -#define BUF_SIZE_GROW (4*1024) - - -char * dmC64GetImageTypeString(char *buf, const size_t len, const int type) -{ - snprintf(buf, len, - "%s%s%s", - (type & D64_FMT_FLI) ? "FLI " : "", - (type & D64_FMT_MC) ? "MCol" : "HiRes", - (type & D64_FMT_ILACE) ? " Ilace" : "" - ); - - return buf; -} - - -// Based on Pepto's palette, stolen from VICE -DMColor dmC64Palette[C64_NCOLORS] = -{ - { 0x00, 0x00, 0x00, 0xff }, - { 0xFF, 0xFF, 0xFF, 0xff }, - { 0x68, 0x37, 0x2B, 0xff }, - { 0x70, 0xA4, 0xB2, 0xff }, - { 0x6F, 0x3D, 0x86, 0xff }, - { 0x58, 0x8D, 0x43, 0xff }, - { 0x35, 0x28, 0x79, 0xff }, - { 0xB8, 0xC7, 0x6F, 0xff }, - { 0x6F, 0x4F, 0x25, 0xff }, - { 0x43, 0x39, 0x00, 0xff }, - { 0x9A, 0x67, 0x59, 0xff }, - { 0x44, 0x44, 0x44, 0xff }, - { 0x6C, 0x6C, 0x6C, 0xff }, - { 0x9A, 0xD2, 0x84, 0xff }, - { 0x6C, 0x5E, 0xB5, 0xff }, - { 0x95, 0x95, 0x95, 0xff }, -}; - - -const size_t dmC64DefaultSizes[DT_LAST] = -{ - C64_SCR_COLOR_SIZE, - C64_SCR_BITMAP_SIZE, - C64_SCR_SCREEN_SIZE, - 1, - C64_SCR_EXTRADATA, -}; - - -#define DM_GET_ADDR_LO(addr) ((addr) & 0xff) -#define DM_GET_ADDR_HI(addr) (((addr) >> 8) & 0xff) - - -static BOOL dmCompareAddr16(const Uint8 *buf, const size_t offs, const Uint16 addr) -{ - return buf[offs ] == DM_GET_ADDR_LO(addr) && - buf[offs + 1] == DM_GET_ADDR_HI(addr); -} - - -int dmC64ConvertCSDataToImage(DMImage *img, - int xoffs, int yoffs, const Uint8 *buf, - int width, int height, BOOL multicolor, int *colors) -{ - int yc, widthpx = width * 8; - Uint8 *dp; - - if (img == NULL) - return DMERR_NULLPTR; - - if (xoffs < 0 || yoffs < 0 || - xoffs > img->width - widthpx || - yoffs > img->height - height) - return DMERR_INVALID_ARGS; - - dp = img->data + (yoffs * img->pitch) + xoffs; - - if (multicolor) - { - for (yc = 0; yc < height; yc++) - { - const int offs = yc * width; - int xc; - Uint8 *d = dp; - - for (xc = 0; xc < widthpx / 2; xc++) - { - const int b = buf[offs + (xc / 4)]; - const int v = 6 - ((xc * 2) & 6); - const Uint8 c = colors[(b >> v) & 3]; - - *d++ = c; - *d++ = c; - } - - dp += img->pitch; - } - } - else - { - for (yc = 0; yc < height; yc++) - { - const int offs = yc * width; - int xc; - Uint8 *d = dp; - - for (xc = 0; xc < widthpx; xc++) - { - const int b = buf[offs + (xc / 8)]; - const int v = 7 - (xc & 7); - const Uint8 c = colors[(b >> v) & 1]; - - *d++ = c; - } - - dp += img->pitch; - } - } - - return DMERR_OK; -} - - -static int fmtProbeDrazPaint20Packed(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) -{ - const char *ident = (const char *) buf + 2; - - if (len > 22 && - dmCompareAddr16(buf, 0, fmt->addr) && - strncmp(ident, "DRAZPAINT ", 10) == 0 && - ident[11] == '.' && ( - (ident[10] == '1' && ident[12] == '4') || - (ident[10] == '2' && ident[12] == '0') - )) - return DM_PROBE_SCORE_MAX; - - return DM_PROBE_SCORE_FALSE; -} - - -static int dmDecodeGenericRLE(Uint8 **mem, Uint8 **pdstEnd, const Uint8 *src, const Uint8 *srcEnd, const Uint8 rleMarker) -{ - Uint8 *dst, *dstEnd; - - if ((*mem = dmMalloc(C64_RAM_SIZE)) == NULL) - return DMERR_MALLOC; - - dst = *mem; - dstEnd = *mem + C64_RAM_SIZE; - - while (src <= srcEnd && dst <= dstEnd) - { - int c = *src++; - if (c == rleMarker && src + 2 <= srcEnd) - { - int cnt = *src++; - c = *src++; - while (cnt-- && dst <= dstEnd) - *dst++ = c; - } - else - *dst++ = c; - } - - *pdstEnd = dst; - - return DMERR_OK; -} - - -static int fmtDecodeDrazPaintPacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) -{ - int res; - Uint8 *mem = NULL, *dstEnd; - - if ((res = dmDecodeGenericRLE(&mem, &dstEnd, buf + 0x0e, buf + len, *(buf + 0x0d))) != DMERR_OK) - goto out; - - res = dmC64DecodeGenericBMP(img, mem, dstEnd - mem + 1, fmt); - -out: - dmFree(mem); - return res; -} - - -static int fmtProbeDrazLace10Packed(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) -{ - const char *ident = (const char *) buf + 2; - if (len > 22 && - dmCompareAddr16(buf, 0, fmt->addr) && - strncmp(ident, "DRAZLACE! 1.0", 13) == 0) - return DM_PROBE_SCORE_MAX; - - return DM_PROBE_SCORE_FALSE; -} - - -static BOOL fmtDrazLaceSetLaceType(DMC64Image *img, const struct _DMC64EncDecOp *op, const Uint8 *buf, const size_t len) -{ - (void) len; - - img->laceType = buf[op->offs] ? D64_ILACE_RES : D64_ILACE_COLOR; - img->laceBank1 = img->laceBank2 = 0; - return TRUE; -} - - -#define AMICA_DM_PROBE_SIZE 2048 -static int fmtProbeAmicaPaintPacked(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) -{ - size_t i, n; - if (len < AMICA_DM_PROBE_SIZE || !dmCompareAddr16(buf, 0, fmt->addr)) - return DM_PROBE_SCORE_FALSE; - - // Interpaint Hi-Res gives a false positive - if (len == 9002) - return DM_PROBE_SCORE_FALSE; - - for (n = 0, i = 2; i < len; i++) - if (buf[i] == 0xC2) n++; - - if (n > 50) - return DM_PROBE_SCORE_GOOD; - if (n > 25) - return DM_PROBE_SCORE_AVG; - if (n > 10) - return DM_PROBE_SCORE_MAYBE; - return DM_PROBE_SCORE_FALSE; -} - - -static int fmtDecodeAmicaPaintPacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) -{ - int res; - Uint8 *mem = NULL, *dstEnd; - - if ((res = dmDecodeGenericRLE(&mem, &dstEnd, buf, buf + len, 0xC2)) != DMERR_OK) - goto out; - - res = dmC64DecodeGenericBMP(img, mem, dstEnd - mem + 1, fmt); - -out: - dmFree(mem); - return res; -} - - -static BOOL fmtTruePaintSetLaceType(DMC64Image *img, const struct _DMC64EncDecOp *op, const Uint8 *buf, const size_t len) -{ - (void) op; - (void) buf; - (void) len; - img->laceType = D64_ILACE_RES; - img->laceBank1 = 0; - img->laceBank2 = 1; - return TRUE; -} - - -static BOOL fmtSetFLIType(DMC64Image *img, const struct _DMC64EncDecOp *op, const Uint8 *buf, const size_t len) -{ - (void) buf; - (void) len; - img->fliType = op->bank; - return TRUE; -} - - -const DMC64ImageFormat dmC64ImageFormats[] = -{ - { - D64_FMT_MC, "d2p", "DrazPaint 2.0 (packed)", 0x5800, -1, - fmtProbeDrazPaint20Packed, fmtDecodeDrazPaintPacked, - NULL, NULL, NULL, - 4, - { - { DT_COLOR_RAM, 0x0000, 0, 0, NULL, NULL }, - { DT_BITMAP, 0x0800, 0, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x0400, 0, 0, NULL, NULL }, - { DT_BGCOLOR, 0x2740, 0, 0, NULL, NULL }, - } - }, - - { - D64_FMT_MC | D64_FMT_ILACE, "dlp", "DrazLace 1.0 (packed)", 0x5800, -1, - fmtProbeDrazLace10Packed, fmtDecodeDrazPaintPacked, - NULL, NULL, NULL, - 6, - { - { DT_COLOR_RAM, 0x0000, 0, 0, NULL, NULL }, - { DT_BITMAP, 0x0800, 0, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x0400, 0, 0, NULL, NULL }, - { DT_BGCOLOR, 0x2740, 0, 0, NULL, NULL }, - { DT_BITMAP, 0x2800, 1, 0, NULL, NULL }, - { DT_DEC_FUNCTION, 0x2742, 0, 1, fmtDrazLaceSetLaceType, NULL }, - } - }, - - { - D64_FMT_MC, "drp", "DrazPaint (unpacked)", 0x5800, 10051, - NULL, NULL, - NULL, NULL, NULL, - 4, - { - { DT_COLOR_RAM, 0x0000, 0, 0, NULL, NULL }, - { DT_BITMAP, 0x0800, 0, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x0400, 0, 0, NULL, NULL }, - { DT_BGCOLOR, 0x2740, 0, 0, NULL, NULL }, - } - }, - - { - D64_FMT_MC | D64_FMT_ILACE, "drl", "DrazLace 1.0 (unpacked)", 0x5800, 18242, - NULL, NULL, - NULL, NULL, NULL, - 6, - { - { DT_COLOR_RAM, 0x0000, 0, 0, NULL, NULL }, - { DT_BITMAP, 0x0800, 0, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x0400, 0, 0, NULL, NULL }, - { DT_BGCOLOR, 0x2740, 0, 0, NULL, NULL }, - { DT_BITMAP, 0x2800, 1, 0, NULL, NULL }, - { DT_DEC_FUNCTION, 0x2742, 0, 1, fmtDrazLaceSetLaceType, NULL }, - } - }, - - { - D64_FMT_MC | D64_FMT_ILACE, "mci", "Truepaint (unpacked)", 0x9c00, 19434, - NULL, NULL, - NULL, NULL, NULL, - 6, - { - { DT_SCREEN_RAM, 0x0000, 0, 0, NULL, NULL }, - { DT_BGCOLOR, 0x03e8, 0, 0, NULL, NULL }, - { DT_BITMAP, 0x0400, 0, 0, NULL, NULL }, - { DT_BITMAP, 0x2400, 1, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x4400, 1, 0, NULL, NULL }, - { DT_COLOR_RAM, 0x4800, 0, 0, NULL, NULL }, - { DT_DEC_FUNCTION, 0x0000, 0, 0, fmtTruePaintSetLaceType, NULL }, - } - }, - - { - D64_FMT_MC, "kla", "Koala Paint (unpacked)", 0x6000, 10003, - NULL, NULL, - NULL, NULL, NULL, - 4, - { - { DT_BITMAP, 0x0000, 0, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL }, - { DT_COLOR_RAM, 0x2328, 0, 0, NULL, NULL }, - { DT_BGCOLOR, 0x2710, 0, 0, NULL, NULL }, - } - }, - - { - D64_FMT_MC, "ocp", "Advanced Art Studio (unpacked)", 0x2000, 10018, - NULL, NULL, - NULL, NULL, NULL, - 4, - { - { DT_BITMAP, 0x0000, 0, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL }, - { DT_COLOR_RAM, 0x2338, 0, 0, NULL, NULL }, - { DT_BGCOLOR, 0x2329, 0, 0, NULL, NULL }, - } - }, - - { - D64_FMT_MC, "ami", "Amica Paint (packed)", 0x4000, -1, - fmtProbeAmicaPaintPacked, fmtDecodeAmicaPaintPacked, - NULL, NULL, NULL, - 4, - { - { DT_COLOR_RAM, 0x2328, 0, 0, NULL, NULL }, - { DT_BITMAP, 0x0000, 0, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL }, - { DT_BGCOLOR, 0x2710, 0, 0, NULL, NULL }, - } - }, - - { - D64_FMT_MC, "rpm", "Run Paint (unpacked)", 0x6000, 10006, - NULL, NULL, - NULL, NULL, NULL, - 4, - { - { DT_COLOR_RAM, 0x2328, 0, 0, NULL, NULL }, - { DT_BITMAP, 0x0000, 0, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL }, - { DT_BGCOLOR, 0x2710, 0, 0, NULL, NULL }, - } - }, - - { - D64_FMT_HIRES, "art", "Art Studio (unpacked)", 0x2000, 9009, - NULL, NULL, - NULL, NULL, NULL, - 2, - { - { DT_BITMAP, 0x0000, 0, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL }, - } - }, - - { - D64_FMT_HIRES, "iph", "Interpaint (unpacked)", 0x4000, 9002, - NULL, NULL, - NULL, NULL, NULL, - 2, - { - { DT_BITMAP, 0x0000, 0, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL }, - } - }, - - { - D64_FMT_HIRES, "dd", "Doodle (unpacked)", 0x1c00, 9218, - NULL, NULL, - NULL, NULL, NULL, - 2, - { - { DT_SCREEN_RAM, 0x0000, 0, 0, NULL, NULL }, - { DT_BITMAP, 0x0400, 0, 0, NULL, NULL }, - } - }, - - { - D64_FMT_MC | D64_FMT_FLI, "bml", "Blackmail FLI (unpacked)", 0x3b00, 17474, - NULL, NULL, - NULL, NULL, NULL, - 11, - { - { DT_COLOR_RAM, 0x0100, 0, 0, NULL, NULL }, - - { DT_SCREEN_RAM, 0x0500, 0, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x0900, 1, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x0d00, 2, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x1100, 3, 0, NULL, NULL }, - - { DT_SCREEN_RAM, 0x1500, 4, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x1900, 5, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x1d00, 6, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x2100, 7, 0, NULL, NULL }, - - { DT_BITMAP, 0x2500, 0, 0, NULL, NULL }, - { DT_DEC_FUNCTION, 0x0000, D64_FLI_8BANK, 0, fmtSetFLIType, NULL }, - } - }, - - { - D64_FMT_MC | D64_FMT_FLI, "fli", "FLI Designer (unpacked)", 0x3c00, 17409, - NULL, NULL, - NULL, NULL, NULL, - 11, - { - { DT_COLOR_RAM, 0x0000, 0, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x0400, 0, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x0800, 1, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x0c00, 2, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x1000, 3, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x1400, 4, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x1800, 5, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x1c00, 6, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x2000, 7, 0, NULL, NULL }, - { DT_BITMAP, 0x2400, 0, 0, NULL, NULL }, - { DT_DEC_FUNCTION, 0x0000, D64_FLI_8BANK, 0, fmtSetFLIType, NULL }, - } - }, - - { - D64_FMT_MC, "xx1", "Unknown $2000 format (unpacked)", 0x2000, 10242, - NULL, NULL, - NULL, NULL, NULL, - 4, - { - { DT_BITMAP, 0x0000, 0, 0, NULL, NULL }, - { DT_SCREEN_RAM, 0x2000, 0, 0, NULL, NULL }, - { DT_COLOR_RAM, 0x2400, 0, 0, NULL, NULL }, - { DT_BGCOLOR_SET, 0x00 , 0, 0, NULL, NULL }, - } - }, - -}; - -const int ndmC64ImageFormats = sizeof(dmC64ImageFormats) / sizeof(dmC64ImageFormats[0]); - - -// Perform probing of the given data buffer, trying to determine -// if it contains a supported "C64" image format. Returns the -// "probe score", see libgfx.h for list of values. If a match -// is found, pointer to format description is set to *pfmt. -int dmC64ProbeBMP(const Uint8 *buf, const size_t len, const DMC64ImageFormat **pfmt) -{ - int i, scoreMax = DM_PROBE_SCORE_FALSE, scoreIndex = -1; - - for (i = 0; i < ndmC64ImageFormats; i++) - { - const DMC64ImageFormat *fmt = &dmC64ImageFormats[i]; - int score = DM_PROBE_SCORE_FALSE; - if (fmt->probe == NULL && fmt->size > 0 && fmt->addr > 0) - { - // Generic probe just checks matching size and load address - if (len == fmt->size && dmCompareAddr16(buf, 0, fmt->addr)) - score = DM_PROBE_SCORE_GOOD; - } - else - score = fmt->probe(buf, len, fmt); - - if (score > scoreMax) - { - scoreMax = score; - scoreIndex = i; - } - } - - if (scoreIndex >= 0) - { - *pfmt = &dmC64ImageFormats[scoreIndex]; - return scoreMax; - } - else - return DM_PROBE_SCORE_FALSE; -} - - -static int dmC64SanityCheckEncDecOp(const int i, const DMC64EncDecOp *op) -{ - if (op->bank < 0 || op->bank >= C64_SCR_MAX_BANK) - { - dmError("Invalid bank %d definition in generic encode/decode operator %d @ #%d.\n", - op->bank, op->type, i); - return DMERR_INTERNAL; - } - - if (op->type < 0 || op->type >= DT_LAST) - { - dmError("Invalid encode/decode operator type %d @ #%d.\n", - op->type, i); - return DMERR_INTERNAL; - } - - return DMERR_OK; -} - - -int dmC64DecodeGenericBMP(DMC64Image *img, const Uint8 *buf, - const size_t len, const DMC64ImageFormat *fmt) -{ - int i; - - if (buf == NULL || img == NULL || fmt == NULL) - return DMERR_NULLPTR; - - // Clear the image structure - memset(img, 0, sizeof(*img)); - img->type = fmt->type; - - // Perform decoding - for (i = 0; i < fmt->nencdecOps; i++) - { - const DMC64EncDecOp *op = &fmt->encdecOps[i]; - const Uint8 *src; - size_t size; - int res; - - // Check operation validity - if ((res = dmC64SanityCheckEncDecOp(i, op)) != DMERR_OK) - return res; - - // Check size - size = (op->size == 0) ? dmC64DefaultSizes[op->type] : op->size; - - // Do we need to reallocate some more space? - if (op->offs + size > len) - { - dmError("Decode out of bounds, op #%d type=%d, offs=%d ($%04x), " - "bank=%d, size=%d ($%04x) @ %d ($%04x)\n", - i, op->type, op->offs, op->offs, op->bank, size, size, len, len); - return DMERR_INVALID_DATA; - } - - src = buf + op->offs; - - // Perform operation - switch (op->type) - { - case DT_COLOR_RAM: memcpy(img->color[op->bank], src, size); break; - case DT_BITMAP: memcpy(img->bitmap[op->bank], src, size); break; - case DT_SCREEN_RAM: memcpy(img->screen[op->bank], src, size); break; - case DT_BGCOLOR: img->bgcolor = *src; break; - case DT_BGCOLOR_SET: img->bgcolor = op->offs; break; - case DT_EXTRADATA: memcpy(img->extradata, src, size); break; - case DT_DEC_FUNCTION: - if (op->decfunction == NULL) - { - dmError("Decode op is a function, but function ptr is NULL: " - "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", - i, op->offs, op->offs, op->bank, size, size, len, len); - return DMERR_INTERNAL; - } - if (!op->decfunction(img, op, buf, len)) - { - dmError("Decode op custom function failed: op #%d, " - "offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", - i, op->offs, op->offs, op->bank, size, size, len, len); - return DMERR_INTERNAL; - } - break; - } - } - - return DMERR_OK; -} - - -int dmC64EncodeGenericBMP(Uint8 **pbuf, size_t *plen, const DMC64Image *img, const DMC64ImageFormat *fmt) -{ - int i, res = DMERR_OK; - Uint8 *buf; - size_t allocated; - - if (pbuf == NULL || plen == NULL || img == NULL || fmt == NULL) - return DMERR_NULLPTR; - - // Allocate the output buffer - *plen = 0; - if (fmt->size > 0) - *plen = allocated = fmt->size; - else - allocated = 8 * 1024; - - if ((buf = dmMalloc(allocated)) == NULL) - { - dmError("Could not allocate %d bytes of memory for C64 image encoding buffer.\n", - allocated); - res = DMERR_MALLOC; - goto error; - } - - // Perform encoding - for (i = 0; i < fmt->nencdecOps; i++) - { - const DMC64EncDecOp *op = &fmt->encdecOps[i]; - Uint8 *dst = 2 + buf + op->offs; - size_t size; - - // Check operation validity - if ((res = dmC64SanityCheckEncDecOp(i, op)) != DMERR_OK) - goto error; - - // Check size - size = (op->size == 0) ? dmC64DefaultSizes[op->type] : op->size; - - // Do we need to reallocate some more space? - if (2 + op->offs + size > allocated) - { - size_t diff = allocated - (op->offs + size + 2), - grow = (diff / (BUF_SIZE_GROW - 1)) * BUF_SIZE_GROW; - allocated += grow; - - if ((buf = dmRealloc(buf, allocated)) == NULL) - { - dmError("Could not re-allocate %d bytes of memory for C64 image encoding buffer.\n", - allocated); - res = DMERR_MALLOC; - goto error; - } - } - - if (fmt->size == 0 && op->offs + size + 2 > *plen) - *plen = op->offs + size + 2; - - // Perform operation - switch (op->type) - { - case DT_COLOR_RAM: memcpy(dst, img->color[op->bank], size); break; - case DT_BITMAP: memcpy(dst, img->bitmap[op->bank], size); break; - case DT_SCREEN_RAM: memcpy(dst, img->screen[op->bank], size); break; - case DT_BGCOLOR: *dst = img->bgcolor; break; - case DT_EXTRADATA: memcpy(dst, img->extradata, size); break; - case DT_ENC_FUNCTION: - if (op->encfunction == NULL) - { - dmError("Encode op is a function, but function ptr is NULL: " - "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", - i, op->offs, op->offs, op->bank, size, size, *plen, *plen); - return DMERR_INTERNAL; - } - /* - if (!op->encfunction(op, buf, len)) - { - dmError("Encode op custom function failed: op #%d, " - "offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", - i, op->offs, op->offs, op->bank, size, size, len, len); - return DMERR_INTERNAL; - } - */ - break; - } - } - - buf[0] = DM_GET_ADDR_LO(fmt->addr); - buf[1] = DM_GET_ADDR_HI(fmt->addr); - - *pbuf = buf; - return DMERR_OK; - -error: - dmFree(buf); - *pbuf = NULL; - *plen = 0; - return res; -} - - -static inline Uint8 dmC64GetMCColor(const DMC64Image *img, const int bits, const int cbank, const int vbank, const int scroffs) -{ - switch (bits) - { - case 0: return img->bgcolor; break; - case 1: return img->screen[vbank][scroffs] >> 4; break; - case 2: return img->screen[vbank][scroffs] & 15; break; - default: return img->color[cbank][scroffs] & 15; break; - } -} - - -// Convert a generic "C64" format bitmap in DMC64Image struct to -// a indexed/paletted bitmap image. -int dmC64ConvertGenericBMP2Image(DMImage *dst, const DMC64Image *src, const BOOL doubleMC) -{ - Uint8 *dp = dst->data; - int yc; - - // Sanity check arguments - if (dst == NULL || src == NULL) - return DMERR_NULLPTR; - - if (dst->width < 8) - return DMERR_INVALID_ARGS; - - // Perform generic conversion - for (yc = 0; yc < dst->height; yc++) - { - Uint8 *d = dp; - const int y = yc / 8, yb = yc & 7; - const int scroffsy = y * C64_SCR_CH_WIDTH; - const int bmoffsy = y * C64_SCR_WIDTH; - int xc; - - if ((src->type & D64_FMT_MC) == D64_FMT_HIRES) - { - // Hi-res bitmap - for (xc = 0; xc < dst->width; xc++) - { - const int x = xc / 8; - const int scroffs = scroffsy + x; - const int bmoffs = bmoffsy + (x * 8) + yb; - const int v = 7 - (xc & 7); - - if ((src->bitmap[0][bmoffs] >> v) & 1) - *d++ = src->screen[0][scroffs] >> 4; - else - *d++ = src->screen[0][scroffs] & 15; - } - } - else - { - // Multicolor variants - const int wdivisor = doubleMC ? 2 : 1; - - for (xc = 0; xc < dst->width / wdivisor; xc++) - { - const int x = xc / 4; - const int scroffs = scroffsy + x; - const int bmoffs = bmoffsy + (x * 8) + yb; - const int v = 6 - ((xc * 2) & 6); - Uint8 c; - - if (src->type & D64_FMT_FLI) - { - int vbank = 0; - switch (src->fliType) - { - case D64_FLI_2BANK: - vbank = yb / 4; - break; - case D64_FLI_4BANK: - vbank = yb / 2; - break; - case D64_FLI_8BANK: - vbank = yb; - break; - } - c = dmC64GetMCColor(src, (src->bitmap[0][bmoffs] >> v) & 3, 0, vbank, scroffs); - *d++ = c; - if (doubleMC) - *d++ = c; - } - else - if (src->type & D64_FMT_ILACE) - { - *d++ = dmC64GetMCColor(src, (src->bitmap[0][bmoffs] >> v) & 3, 0, src->laceBank1, scroffs); - if (doubleMC) - *d++ = dmC64GetMCColor(src, (src->bitmap[1][bmoffs] >> v) & 3, 0, src->laceBank2, scroffs); - } - else - { - c = dmC64GetMCColor(src, (src->bitmap[0][bmoffs] >> v) & 3, 0, 0, scroffs); - *d++ = c; - if (doubleMC) - *d++ = c; - } - } - } - dp += dst->pitch; - } - - return DMERR_OK; -} - - -int dmC64ConvertBMP2Image(DMImage **pdst, const DMC64Image *src, const DMC64ImageFormat *fmt, const BOOL doubleMC) -{ - int width, res; - DMImage *dst; - - if (pdst == NULL || src == NULL) - return DMERR_NULLPTR; - - // Calculate output image width - if ((src->type & D64_FMT_MC) && !doubleMC) - width = C64_SCR_WIDTH / 2; - else - width = C64_SCR_WIDTH; - - // Allocate image structure - if ((*pdst = dst = dmImageAlloc(width, C64_SCR_HEIGHT)) == NULL) - return DMERR_MALLOC; - - // Set palette - dst->pal = (DMColor *) &dmC64Palette; - dst->ncolors = C64_NCOLORS; - dst->constpal = TRUE; - - // Convert - if (fmt->convertFrom != NULL) - res = fmt->convertFrom(dst, src, doubleMC); - else - res = dmC64ConvertGenericBMP2Image(dst, src, doubleMC); - - return res; -} - - -int dmC64DecodeBMP(DMC64Image *img, const Uint8 *buf, const size_t len, - const size_t probeOffs, const size_t loadOffs, - const DMC64ImageFormat **fmt, const DMC64ImageFormat *forced) -{ - // Check for forced format - if (forced != NULL) - *fmt = forced; - else - { - // Nope, perform a generic probe - if (probeOffs >= len) - return -200; - - if (dmC64ProbeBMP(buf + probeOffs, len - probeOffs, fmt) == DM_PROBE_SCORE_FALSE) - return -201; - } - - if (loadOffs >= len) - return -203; - - // Decode the bitmap to memory layout - if ((*fmt)->decode != NULL) - return (*fmt)->decode(img, buf + loadOffs, len - loadOffs, *fmt); - else - return dmC64DecodeGenericBMP(img, buf + loadOffs, len - loadOffs, *fmt); -}
--- a/src/lib64gfx.h Mon Feb 23 22:55:32 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,195 +0,0 @@ -/* - * Functions for reading and converting various restricted - * C64/etc and/or indexed/paletted graphics formats. - * Programmed and designed by Matti 'ccr' Hamalainen - * (C) Copyright 2012 Tecnic Software productions (TNSP) - * - * Please read file 'COPYING' for information on license and distribution. - */ -#ifndef LIB64GFX_H -#define LIB64GFX_H 1 - -#include "libgfx.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -// Bitmap constants -#define C64_SCR_WIDTH 320 -#define C64_SCR_HEIGHT 200 -#define C64_SCR_CH_WIDTH (C64_SCR_WIDTH/8) -#define C64_SCR_CH_HEIGHT (C64_SCR_HEIGHT/8) -#define C64_SCR_COLOR_SIZE (C64_SCR_CH_WIDTH * C64_SCR_CH_HEIGHT) -#define C64_SCR_SCREEN_SIZE (C64_SCR_CH_WIDTH * C64_SCR_CH_HEIGHT) -#define C64_SCR_BITMAP_SIZE (C64_SCR_WIDTH * C64_SCR_HEIGHT/8) -#define C64_SCR_EXTRADATA 1024 -#define C64_SCR_MAX_BANK 8 - -// C64 video screen pixel aspect ratio on PAL -#define C64_SCR_PAR_XY (0.9365f) - -// Sprite constants -#define C64_SPR_WIDTH 3 // bytes -#define C64_SPR_HEIGHT 21 // lines -#define C64_SPR_WIDTH_PX (8 * C64_SPR_WIDTH) -#define C64_SPR_SIZE ((C64_SPR_WIDTH * C64_SPR_HEIGHT) + 1) - -// Character constants -#define C64_CHR_WIDTH 1 // bytes -#define C64_CHR_HEIGHT 8 // lines -#define C64_CHR_WIDTH_PX (8 * C64_CHR_WIDTH) -#define C64_CHR_SIZE (C64_CHR_WIDTH * C64_CHR_HEIGHT) - -// Etc. -#define C64_RAM_SIZE (64*1024) -#define C64_NCOLORS 16 -#define C64_MAX_COLORS 16 -#define C64_VIDBANK_SIZE (16*1024) -#define C64_MAX_SPRITES (C64_VIDBANK_SIZE / C64_SPR_SIZE) -#define C64_MAX_CHARS 256 - -// Different supported C64 bitmap "modes" -enum -{ - D64_FMT_HIRES = 0x0000, - D64_FMT_MC = 0x0001, - D64_FMT_ILACE = 0x0002, - D64_FMT_FLI = 0x0004, - - D64_FMT_MODE_MASK = 0x000f, - -}; - -enum -{ - D64_FLI_2BANK, - D64_FLI_4BANK, - D64_FLI_8BANK, -}; - -enum -{ - D64_ILACE_COLOR, - D64_ILACE_RES, -}; - -typedef struct -{ - BOOL multicolor, xexpand, yexpand; - int color, xc, yc; - Uint8 data[C64_SPR_HEIGHT][C64_SPR_WIDTH]; -} DMC64Sprite; - -enum -{ - D64_CHR_GLOBAL, // use font-global setting - D64_CHR_MULTICOLOR, // character is multicolor - D64_CHR_HIRES, -}; - -typedef struct -{ - int mode, color; - Uint8 data[C64_CHR_HEIGHT]; -} DMC64Char; - - -typedef struct -{ - BOOL multicolor; - int colbg, color, col1, col2; - int nglyphs; - DMC64Char *glyphs; -} DMC64Font; - - - -typedef struct -{ - int type, // Image type (D64_FMT_*) - fliType, // FLI type (if FLI used) - laceType, // Interlace type (D64_ILACE_*) - laceBank1, - laceBank2; - - Uint8 color[C64_SCR_MAX_BANK][C64_SCR_COLOR_SIZE], - bitmap[C64_SCR_MAX_BANK][C64_SCR_BITMAP_SIZE], - screen[C64_SCR_MAX_BANK][C64_SCR_SCREEN_SIZE], - extradata[C64_SCR_EXTRADATA], - d020, bgcolor, d022, d023, d024; - - Uint8 charset[C64_MAX_CHARS][C64_CHR_HEIGHT * C64_CHR_WIDTH]; - DMC64Sprite sprites[C64_MAX_SPRITES]; -} DMC64Image; - - -enum -{ - DT_COLOR_RAM, - DT_BITMAP, - DT_SCREEN_RAM, - DT_BGCOLOR, - DT_BGCOLOR_SET, - DT_EXTRADATA, - - DT_DEC_FUNCTION, - DT_ENC_FUNCTION, - - DT_LAST, -}; - - -typedef struct _DMC64EncDecOp -{ - int type; - size_t offs; - int bank; - size_t size; - BOOL (*decfunction)(DMC64Image *img, const struct _DMC64EncDecOp *op, const Uint8 *buf, const size_t len); - BOOL (*encfunction)(const struct _DMC64EncDecOp *op, Uint8 **buf, size_t *len, const DMC64Image *img); -} DMC64EncDecOp; - - -typedef struct _DMC64ImageFormat -{ - int type; - char *fext; - char *name; - size_t addr; // Loading address (0 if no loading address) - size_t size; // Size, including loading address. Only used in encoding, if even there (0 if no static size) - int (*probe)(const Uint8 *buf, const size_t len, const struct _DMC64ImageFormat *fmt); - int (*decode)(DMC64Image *img, const Uint8 *buf, const size_t len, const struct _DMC64ImageFormat *fmt); - int (*encode)(DMC64Image *img, Uint8 **buf, size_t *len, const struct _DMC64ImageFormat *fmt); - int (*convertFrom)(DMImage *, const DMC64Image *, const BOOL doubleMC); - int (*convertTo)(DMImage *, DMC64Image *); - - int nencdecOps; - DMC64EncDecOp encdecOps[16]; -} DMC64ImageFormat; - - -extern const size_t dmC64DefaultSizes[DT_LAST]; -extern DMColor dmC64Palette[C64_NCOLORS]; -extern const DMC64ImageFormat dmC64ImageFormats[]; -extern const int ndmC64ImageFormats; - - -char * dmC64GetImageTypeString(char *buf, const size_t len, const int type); -int dmC64ConvertCSDataToImage(DMImage *img, int xoffs, int yoffs, const Uint8 *inBuf, int width, int height, BOOL multicolor, int *colors); - -int dmC64DecodeGenericBMP(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt); -int dmC64EncodeGenericBMP(Uint8 **pbuf, size_t *plen, const DMC64Image *img, const DMC64ImageFormat *fmt); -int dmC64ConvertGenericBMP2Image(DMImage *dst, const DMC64Image *src, const BOOL doubleMC); - -int dmC64ConvertBMP2Image(DMImage **pdst, const DMC64Image *src, const DMC64ImageFormat *fmt, const BOOL doubleMC); -int dmC64ProbeBMP(const Uint8 *buf, const size_t len, const DMC64ImageFormat **fmt); -int dmC64DecodeBMP(DMC64Image *img, const Uint8 *buf, const size_t len, const size_t probeOffs, const size_t loadOffs, const DMC64ImageFormat **fmt, const DMC64ImageFormat *forced); - - -#ifdef __cplusplus -} -#endif - -#endif // LIB64GFX_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/lib64gfx.c Tue Feb 24 00:47:39 2015 +0200 @@ -0,0 +1,893 @@ +/* + * Functions for reading and converting various restricted + * C64/etc and/or indexed/paletted graphics formats. + * Programmed and designed by Matti 'ccr' Hamalainen + * (C) Copyright 2012 Tecnic Software productions (TNSP) + * + * Please read file 'COPYING' for information on license and distribution. + */ +#include "lib64gfx.h" + +#define BUF_SIZE_INITIAL (16*1024) +#define BUF_SIZE_GROW (4*1024) + + +char * dmC64GetImageTypeString(char *buf, const size_t len, const int type) +{ + snprintf(buf, len, + "%s%s%s", + (type & D64_FMT_FLI) ? "FLI " : "", + (type & D64_FMT_MC) ? "MCol" : "HiRes", + (type & D64_FMT_ILACE) ? " Ilace" : "" + ); + + return buf; +} + + +// Based on Pepto's palette, stolen from VICE +DMColor dmC64Palette[C64_NCOLORS] = +{ + { 0x00, 0x00, 0x00, 0xff }, + { 0xFF, 0xFF, 0xFF, 0xff }, + { 0x68, 0x37, 0x2B, 0xff }, + { 0x70, 0xA4, 0xB2, 0xff }, + { 0x6F, 0x3D, 0x86, 0xff }, + { 0x58, 0x8D, 0x43, 0xff }, + { 0x35, 0x28, 0x79, 0xff }, + { 0xB8, 0xC7, 0x6F, 0xff }, + { 0x6F, 0x4F, 0x25, 0xff }, + { 0x43, 0x39, 0x00, 0xff }, + { 0x9A, 0x67, 0x59, 0xff }, + { 0x44, 0x44, 0x44, 0xff }, + { 0x6C, 0x6C, 0x6C, 0xff }, + { 0x9A, 0xD2, 0x84, 0xff }, + { 0x6C, 0x5E, 0xB5, 0xff }, + { 0x95, 0x95, 0x95, 0xff }, +}; + + +const size_t dmC64DefaultSizes[DT_LAST] = +{ + C64_SCR_COLOR_SIZE, + C64_SCR_BITMAP_SIZE, + C64_SCR_SCREEN_SIZE, + 1, + C64_SCR_EXTRADATA, +}; + + +#define DM_GET_ADDR_LO(addr) ((addr) & 0xff) +#define DM_GET_ADDR_HI(addr) (((addr) >> 8) & 0xff) + + +static BOOL dmCompareAddr16(const Uint8 *buf, const size_t offs, const Uint16 addr) +{ + return buf[offs ] == DM_GET_ADDR_LO(addr) && + buf[offs + 1] == DM_GET_ADDR_HI(addr); +} + + +int dmC64ConvertCSDataToImage(DMImage *img, + int xoffs, int yoffs, const Uint8 *buf, + int width, int height, BOOL multicolor, int *colors) +{ + int yc, widthpx = width * 8; + Uint8 *dp; + + if (img == NULL) + return DMERR_NULLPTR; + + if (xoffs < 0 || yoffs < 0 || + xoffs > img->width - widthpx || + yoffs > img->height - height) + return DMERR_INVALID_ARGS; + + dp = img->data + (yoffs * img->pitch) + xoffs; + + if (multicolor) + { + for (yc = 0; yc < height; yc++) + { + const int offs = yc * width; + int xc; + Uint8 *d = dp; + + for (xc = 0; xc < widthpx / 2; xc++) + { + const int b = buf[offs + (xc / 4)]; + const int v = 6 - ((xc * 2) & 6); + const Uint8 c = colors[(b >> v) & 3]; + + *d++ = c; + *d++ = c; + } + + dp += img->pitch; + } + } + else + { + for (yc = 0; yc < height; yc++) + { + const int offs = yc * width; + int xc; + Uint8 *d = dp; + + for (xc = 0; xc < widthpx; xc++) + { + const int b = buf[offs + (xc / 8)]; + const int v = 7 - (xc & 7); + const Uint8 c = colors[(b >> v) & 1]; + + *d++ = c; + } + + dp += img->pitch; + } + } + + return DMERR_OK; +} + + +static int fmtProbeDrazPaint20Packed(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) +{ + const char *ident = (const char *) buf + 2; + + if (len > 22 && + dmCompareAddr16(buf, 0, fmt->addr) && + strncmp(ident, "DRAZPAINT ", 10) == 0 && + ident[11] == '.' && ( + (ident[10] == '1' && ident[12] == '4') || + (ident[10] == '2' && ident[12] == '0') + )) + return DM_PROBE_SCORE_MAX; + + return DM_PROBE_SCORE_FALSE; +} + + +static int dmDecodeGenericRLE(Uint8 **mem, Uint8 **pdstEnd, const Uint8 *src, const Uint8 *srcEnd, const Uint8 rleMarker) +{ + Uint8 *dst, *dstEnd; + + if ((*mem = dmMalloc(C64_RAM_SIZE)) == NULL) + return DMERR_MALLOC; + + dst = *mem; + dstEnd = *mem + C64_RAM_SIZE; + + while (src <= srcEnd && dst <= dstEnd) + { + int c = *src++; + if (c == rleMarker && src + 2 <= srcEnd) + { + int cnt = *src++; + c = *src++; + while (cnt-- && dst <= dstEnd) + *dst++ = c; + } + else + *dst++ = c; + } + + *pdstEnd = dst; + + return DMERR_OK; +} + + +static int fmtDecodeDrazPaintPacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) +{ + int res; + Uint8 *mem = NULL, *dstEnd; + + if ((res = dmDecodeGenericRLE(&mem, &dstEnd, buf + 0x0e, buf + len, *(buf + 0x0d))) != DMERR_OK) + goto out; + + res = dmC64DecodeGenericBMP(img, mem, dstEnd - mem + 1, fmt); + +out: + dmFree(mem); + return res; +} + + +static int fmtProbeDrazLace10Packed(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) +{ + const char *ident = (const char *) buf + 2; + if (len > 22 && + dmCompareAddr16(buf, 0, fmt->addr) && + strncmp(ident, "DRAZLACE! 1.0", 13) == 0) + return DM_PROBE_SCORE_MAX; + + return DM_PROBE_SCORE_FALSE; +} + + +static BOOL fmtDrazLaceSetLaceType(DMC64Image *img, const struct _DMC64EncDecOp *op, const Uint8 *buf, const size_t len) +{ + (void) len; + + img->laceType = buf[op->offs] ? D64_ILACE_RES : D64_ILACE_COLOR; + img->laceBank1 = img->laceBank2 = 0; + return TRUE; +} + + +#define AMICA_DM_PROBE_SIZE 2048 +static int fmtProbeAmicaPaintPacked(const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) +{ + size_t i, n; + if (len < AMICA_DM_PROBE_SIZE || !dmCompareAddr16(buf, 0, fmt->addr)) + return DM_PROBE_SCORE_FALSE; + + // Interpaint Hi-Res gives a false positive + if (len == 9002) + return DM_PROBE_SCORE_FALSE; + + for (n = 0, i = 2; i < len; i++) + if (buf[i] == 0xC2) n++; + + if (n > 50) + return DM_PROBE_SCORE_GOOD; + if (n > 25) + return DM_PROBE_SCORE_AVG; + if (n > 10) + return DM_PROBE_SCORE_MAYBE; + return DM_PROBE_SCORE_FALSE; +} + + +static int fmtDecodeAmicaPaintPacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) +{ + int res; + Uint8 *mem = NULL, *dstEnd; + + if ((res = dmDecodeGenericRLE(&mem, &dstEnd, buf, buf + len, 0xC2)) != DMERR_OK) + goto out; + + res = dmC64DecodeGenericBMP(img, mem, dstEnd - mem + 1, fmt); + +out: + dmFree(mem); + return res; +} + + +static BOOL fmtTruePaintSetLaceType(DMC64Image *img, const struct _DMC64EncDecOp *op, const Uint8 *buf, const size_t len) +{ + (void) op; + (void) buf; + (void) len; + img->laceType = D64_ILACE_RES; + img->laceBank1 = 0; + img->laceBank2 = 1; + return TRUE; +} + + +static BOOL fmtSetFLIType(DMC64Image *img, const struct _DMC64EncDecOp *op, const Uint8 *buf, const size_t len) +{ + (void) buf; + (void) len; + img->fliType = op->bank; + return TRUE; +} + + +const DMC64ImageFormat dmC64ImageFormats[] = +{ + { + D64_FMT_MC, "d2p", "DrazPaint 2.0 (packed)", 0x5800, -1, + fmtProbeDrazPaint20Packed, fmtDecodeDrazPaintPacked, + NULL, NULL, NULL, + 4, + { + { DT_COLOR_RAM, 0x0000, 0, 0, NULL, NULL }, + { DT_BITMAP, 0x0800, 0, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x0400, 0, 0, NULL, NULL }, + { DT_BGCOLOR, 0x2740, 0, 0, NULL, NULL }, + } + }, + + { + D64_FMT_MC | D64_FMT_ILACE, "dlp", "DrazLace 1.0 (packed)", 0x5800, -1, + fmtProbeDrazLace10Packed, fmtDecodeDrazPaintPacked, + NULL, NULL, NULL, + 6, + { + { DT_COLOR_RAM, 0x0000, 0, 0, NULL, NULL }, + { DT_BITMAP, 0x0800, 0, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x0400, 0, 0, NULL, NULL }, + { DT_BGCOLOR, 0x2740, 0, 0, NULL, NULL }, + { DT_BITMAP, 0x2800, 1, 0, NULL, NULL }, + { DT_DEC_FUNCTION, 0x2742, 0, 1, fmtDrazLaceSetLaceType, NULL }, + } + }, + + { + D64_FMT_MC, "drp", "DrazPaint (unpacked)", 0x5800, 10051, + NULL, NULL, + NULL, NULL, NULL, + 4, + { + { DT_COLOR_RAM, 0x0000, 0, 0, NULL, NULL }, + { DT_BITMAP, 0x0800, 0, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x0400, 0, 0, NULL, NULL }, + { DT_BGCOLOR, 0x2740, 0, 0, NULL, NULL }, + } + }, + + { + D64_FMT_MC | D64_FMT_ILACE, "drl", "DrazLace 1.0 (unpacked)", 0x5800, 18242, + NULL, NULL, + NULL, NULL, NULL, + 6, + { + { DT_COLOR_RAM, 0x0000, 0, 0, NULL, NULL }, + { DT_BITMAP, 0x0800, 0, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x0400, 0, 0, NULL, NULL }, + { DT_BGCOLOR, 0x2740, 0, 0, NULL, NULL }, + { DT_BITMAP, 0x2800, 1, 0, NULL, NULL }, + { DT_DEC_FUNCTION, 0x2742, 0, 1, fmtDrazLaceSetLaceType, NULL }, + } + }, + + { + D64_FMT_MC | D64_FMT_ILACE, "mci", "Truepaint (unpacked)", 0x9c00, 19434, + NULL, NULL, + NULL, NULL, NULL, + 6, + { + { DT_SCREEN_RAM, 0x0000, 0, 0, NULL, NULL }, + { DT_BGCOLOR, 0x03e8, 0, 0, NULL, NULL }, + { DT_BITMAP, 0x0400, 0, 0, NULL, NULL }, + { DT_BITMAP, 0x2400, 1, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x4400, 1, 0, NULL, NULL }, + { DT_COLOR_RAM, 0x4800, 0, 0, NULL, NULL }, + { DT_DEC_FUNCTION, 0x0000, 0, 0, fmtTruePaintSetLaceType, NULL }, + } + }, + + { + D64_FMT_MC, "kla", "Koala Paint (unpacked)", 0x6000, 10003, + NULL, NULL, + NULL, NULL, NULL, + 4, + { + { DT_BITMAP, 0x0000, 0, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL }, + { DT_COLOR_RAM, 0x2328, 0, 0, NULL, NULL }, + { DT_BGCOLOR, 0x2710, 0, 0, NULL, NULL }, + } + }, + + { + D64_FMT_MC, "ocp", "Advanced Art Studio (unpacked)", 0x2000, 10018, + NULL, NULL, + NULL, NULL, NULL, + 4, + { + { DT_BITMAP, 0x0000, 0, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL }, + { DT_COLOR_RAM, 0x2338, 0, 0, NULL, NULL }, + { DT_BGCOLOR, 0x2329, 0, 0, NULL, NULL }, + } + }, + + { + D64_FMT_MC, "ami", "Amica Paint (packed)", 0x4000, -1, + fmtProbeAmicaPaintPacked, fmtDecodeAmicaPaintPacked, + NULL, NULL, NULL, + 4, + { + { DT_COLOR_RAM, 0x2328, 0, 0, NULL, NULL }, + { DT_BITMAP, 0x0000, 0, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL }, + { DT_BGCOLOR, 0x2710, 0, 0, NULL, NULL }, + } + }, + + { + D64_FMT_MC, "rpm", "Run Paint (unpacked)", 0x6000, 10006, + NULL, NULL, + NULL, NULL, NULL, + 4, + { + { DT_COLOR_RAM, 0x2328, 0, 0, NULL, NULL }, + { DT_BITMAP, 0x0000, 0, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL }, + { DT_BGCOLOR, 0x2710, 0, 0, NULL, NULL }, + } + }, + + { + D64_FMT_HIRES, "art", "Art Studio (unpacked)", 0x2000, 9009, + NULL, NULL, + NULL, NULL, NULL, + 2, + { + { DT_BITMAP, 0x0000, 0, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL }, + } + }, + + { + D64_FMT_HIRES, "iph", "Interpaint (unpacked)", 0x4000, 9002, + NULL, NULL, + NULL, NULL, NULL, + 2, + { + { DT_BITMAP, 0x0000, 0, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x1f40, 0, 0, NULL, NULL }, + } + }, + + { + D64_FMT_HIRES, "dd", "Doodle (unpacked)", 0x1c00, 9218, + NULL, NULL, + NULL, NULL, NULL, + 2, + { + { DT_SCREEN_RAM, 0x0000, 0, 0, NULL, NULL }, + { DT_BITMAP, 0x0400, 0, 0, NULL, NULL }, + } + }, + + { + D64_FMT_MC | D64_FMT_FLI, "bml", "Blackmail FLI (unpacked)", 0x3b00, 17474, + NULL, NULL, + NULL, NULL, NULL, + 11, + { + { DT_COLOR_RAM, 0x0100, 0, 0, NULL, NULL }, + + { DT_SCREEN_RAM, 0x0500, 0, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x0900, 1, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x0d00, 2, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x1100, 3, 0, NULL, NULL }, + + { DT_SCREEN_RAM, 0x1500, 4, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x1900, 5, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x1d00, 6, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x2100, 7, 0, NULL, NULL }, + + { DT_BITMAP, 0x2500, 0, 0, NULL, NULL }, + { DT_DEC_FUNCTION, 0x0000, D64_FLI_8BANK, 0, fmtSetFLIType, NULL }, + } + }, + + { + D64_FMT_MC | D64_FMT_FLI, "fli", "FLI Designer (unpacked)", 0x3c00, 17409, + NULL, NULL, + NULL, NULL, NULL, + 11, + { + { DT_COLOR_RAM, 0x0000, 0, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x0400, 0, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x0800, 1, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x0c00, 2, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x1000, 3, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x1400, 4, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x1800, 5, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x1c00, 6, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x2000, 7, 0, NULL, NULL }, + { DT_BITMAP, 0x2400, 0, 0, NULL, NULL }, + { DT_DEC_FUNCTION, 0x0000, D64_FLI_8BANK, 0, fmtSetFLIType, NULL }, + } + }, + + { + D64_FMT_MC, "xx1", "Unknown $2000 format (unpacked)", 0x2000, 10242, + NULL, NULL, + NULL, NULL, NULL, + 4, + { + { DT_BITMAP, 0x0000, 0, 0, NULL, NULL }, + { DT_SCREEN_RAM, 0x2000, 0, 0, NULL, NULL }, + { DT_COLOR_RAM, 0x2400, 0, 0, NULL, NULL }, + { DT_BGCOLOR_SET, 0x00 , 0, 0, NULL, NULL }, + } + }, + +}; + +const int ndmC64ImageFormats = sizeof(dmC64ImageFormats) / sizeof(dmC64ImageFormats[0]); + + +// Perform probing of the given data buffer, trying to determine +// if it contains a supported "C64" image format. Returns the +// "probe score", see libgfx.h for list of values. If a match +// is found, pointer to format description is set to *pfmt. +int dmC64ProbeBMP(const Uint8 *buf, const size_t len, const DMC64ImageFormat **pfmt) +{ + int i, scoreMax = DM_PROBE_SCORE_FALSE, scoreIndex = -1; + + for (i = 0; i < ndmC64ImageFormats; i++) + { + const DMC64ImageFormat *fmt = &dmC64ImageFormats[i]; + int score = DM_PROBE_SCORE_FALSE; + if (fmt->probe == NULL && fmt->size > 0 && fmt->addr > 0) + { + // Generic probe just checks matching size and load address + if (len == fmt->size && dmCompareAddr16(buf, 0, fmt->addr)) + score = DM_PROBE_SCORE_GOOD; + } + else + score = fmt->probe(buf, len, fmt); + + if (score > scoreMax) + { + scoreMax = score; + scoreIndex = i; + } + } + + if (scoreIndex >= 0) + { + *pfmt = &dmC64ImageFormats[scoreIndex]; + return scoreMax; + } + else + return DM_PROBE_SCORE_FALSE; +} + + +static int dmC64SanityCheckEncDecOp(const int i, const DMC64EncDecOp *op) +{ + if (op->bank < 0 || op->bank >= C64_SCR_MAX_BANK) + { + dmError("Invalid bank %d definition in generic encode/decode operator %d @ #%d.\n", + op->bank, op->type, i); + return DMERR_INTERNAL; + } + + if (op->type < 0 || op->type >= DT_LAST) + { + dmError("Invalid encode/decode operator type %d @ #%d.\n", + op->type, i); + return DMERR_INTERNAL; + } + + return DMERR_OK; +} + + +int dmC64DecodeGenericBMP(DMC64Image *img, const Uint8 *buf, + const size_t len, const DMC64ImageFormat *fmt) +{ + int i; + + if (buf == NULL || img == NULL || fmt == NULL) + return DMERR_NULLPTR; + + // Clear the image structure + memset(img, 0, sizeof(*img)); + img->type = fmt->type; + + // Perform decoding + for (i = 0; i < fmt->nencdecOps; i++) + { + const DMC64EncDecOp *op = &fmt->encdecOps[i]; + const Uint8 *src; + size_t size; + int res; + + // Check operation validity + if ((res = dmC64SanityCheckEncDecOp(i, op)) != DMERR_OK) + return res; + + // Check size + size = (op->size == 0) ? dmC64DefaultSizes[op->type] : op->size; + + // Do we need to reallocate some more space? + if (op->offs + size > len) + { + dmError("Decode out of bounds, op #%d type=%d, offs=%d ($%04x), " + "bank=%d, size=%d ($%04x) @ %d ($%04x)\n", + i, op->type, op->offs, op->offs, op->bank, size, size, len, len); + return DMERR_INVALID_DATA; + } + + src = buf + op->offs; + + // Perform operation + switch (op->type) + { + case DT_COLOR_RAM: memcpy(img->color[op->bank], src, size); break; + case DT_BITMAP: memcpy(img->bitmap[op->bank], src, size); break; + case DT_SCREEN_RAM: memcpy(img->screen[op->bank], src, size); break; + case DT_BGCOLOR: img->bgcolor = *src; break; + case DT_BGCOLOR_SET: img->bgcolor = op->offs; break; + case DT_EXTRADATA: memcpy(img->extradata, src, size); break; + case DT_DEC_FUNCTION: + if (op->decfunction == NULL) + { + dmError("Decode op is a function, but function ptr is NULL: " + "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", + i, op->offs, op->offs, op->bank, size, size, len, len); + return DMERR_INTERNAL; + } + if (!op->decfunction(img, op, buf, len)) + { + dmError("Decode op custom function failed: op #%d, " + "offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", + i, op->offs, op->offs, op->bank, size, size, len, len); + return DMERR_INTERNAL; + } + break; + } + } + + return DMERR_OK; +} + + +int dmC64EncodeGenericBMP(Uint8 **pbuf, size_t *plen, const DMC64Image *img, const DMC64ImageFormat *fmt) +{ + int i, res = DMERR_OK; + Uint8 *buf; + size_t allocated; + + if (pbuf == NULL || plen == NULL || img == NULL || fmt == NULL) + return DMERR_NULLPTR; + + // Allocate the output buffer + *plen = 0; + if (fmt->size > 0) + *plen = allocated = fmt->size; + else + allocated = 8 * 1024; + + if ((buf = dmMalloc(allocated)) == NULL) + { + dmError("Could not allocate %d bytes of memory for C64 image encoding buffer.\n", + allocated); + res = DMERR_MALLOC; + goto error; + } + + // Perform encoding + for (i = 0; i < fmt->nencdecOps; i++) + { + const DMC64EncDecOp *op = &fmt->encdecOps[i]; + Uint8 *dst = 2 + buf + op->offs; + size_t size; + + // Check operation validity + if ((res = dmC64SanityCheckEncDecOp(i, op)) != DMERR_OK) + goto error; + + // Check size + size = (op->size == 0) ? dmC64DefaultSizes[op->type] : op->size; + + // Do we need to reallocate some more space? + if (2 + op->offs + size > allocated) + { + size_t diff = allocated - (op->offs + size + 2), + grow = (diff / (BUF_SIZE_GROW - 1)) * BUF_SIZE_GROW; + allocated += grow; + + if ((buf = dmRealloc(buf, allocated)) == NULL) + { + dmError("Could not re-allocate %d bytes of memory for C64 image encoding buffer.\n", + allocated); + res = DMERR_MALLOC; + goto error; + } + } + + if (fmt->size == 0 && op->offs + size + 2 > *plen) + *plen = op->offs + size + 2; + + // Perform operation + switch (op->type) + { + case DT_COLOR_RAM: memcpy(dst, img->color[op->bank], size); break; + case DT_BITMAP: memcpy(dst, img->bitmap[op->bank], size); break; + case DT_SCREEN_RAM: memcpy(dst, img->screen[op->bank], size); break; + case DT_BGCOLOR: *dst = img->bgcolor; break; + case DT_EXTRADATA: memcpy(dst, img->extradata, size); break; + case DT_ENC_FUNCTION: + if (op->encfunction == NULL) + { + dmError("Encode op is a function, but function ptr is NULL: " + "op #%d, offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", + i, op->offs, op->offs, op->bank, size, size, *plen, *plen); + return DMERR_INTERNAL; + } + /* + if (!op->encfunction(op, buf, len)) + { + dmError("Encode op custom function failed: op #%d, " + "offs=%d ($%04x), bank=%d, size=%d ($%04x) @ %d ($%04x)\n", + i, op->offs, op->offs, op->bank, size, size, len, len); + return DMERR_INTERNAL; + } + */ + break; + } + } + + buf[0] = DM_GET_ADDR_LO(fmt->addr); + buf[1] = DM_GET_ADDR_HI(fmt->addr); + + *pbuf = buf; + return DMERR_OK; + +error: + dmFree(buf); + *pbuf = NULL; + *plen = 0; + return res; +} + + +static inline Uint8 dmC64GetMCColor(const DMC64Image *img, const int bits, const int cbank, const int vbank, const int scroffs) +{ + switch (bits) + { + case 0: return img->bgcolor; break; + case 1: return img->screen[vbank][scroffs] >> 4; break; + case 2: return img->screen[vbank][scroffs] & 15; break; + default: return img->color[cbank][scroffs] & 15; break; + } +} + + +// Convert a generic "C64" format bitmap in DMC64Image struct to +// a indexed/paletted bitmap image. +int dmC64ConvertGenericBMP2Image(DMImage *dst, const DMC64Image *src, const BOOL doubleMC) +{ + Uint8 *dp = dst->data; + int yc; + + // Sanity check arguments + if (dst == NULL || src == NULL) + return DMERR_NULLPTR; + + if (dst->width < 8) + return DMERR_INVALID_ARGS; + + // Perform generic conversion + for (yc = 0; yc < dst->height; yc++) + { + Uint8 *d = dp; + const int y = yc / 8, yb = yc & 7; + const int scroffsy = y * C64_SCR_CH_WIDTH; + const int bmoffsy = y * C64_SCR_WIDTH; + int xc; + + if ((src->type & D64_FMT_MC) == D64_FMT_HIRES) + { + // Hi-res bitmap + for (xc = 0; xc < dst->width; xc++) + { + const int x = xc / 8; + const int scroffs = scroffsy + x; + const int bmoffs = bmoffsy + (x * 8) + yb; + const int v = 7 - (xc & 7); + + if ((src->bitmap[0][bmoffs] >> v) & 1) + *d++ = src->screen[0][scroffs] >> 4; + else + *d++ = src->screen[0][scroffs] & 15; + } + } + else + { + // Multicolor variants + const int wdivisor = doubleMC ? 2 : 1; + + for (xc = 0; xc < dst->width / wdivisor; xc++) + { + const int x = xc / 4; + const int scroffs = scroffsy + x; + const int bmoffs = bmoffsy + (x * 8) + yb; + const int v = 6 - ((xc * 2) & 6); + Uint8 c; + + if (src->type & D64_FMT_FLI) + { + int vbank = 0; + switch (src->fliType) + { + case D64_FLI_2BANK: + vbank = yb / 4; + break; + case D64_FLI_4BANK: + vbank = yb / 2; + break; + case D64_FLI_8BANK: + vbank = yb; + break; + } + c = dmC64GetMCColor(src, (src->bitmap[0][bmoffs] >> v) & 3, 0, vbank, scroffs); + *d++ = c; + if (doubleMC) + *d++ = c; + } + else + if (src->type & D64_FMT_ILACE) + { + *d++ = dmC64GetMCColor(src, (src->bitmap[0][bmoffs] >> v) & 3, 0, src->laceBank1, scroffs); + if (doubleMC) + *d++ = dmC64GetMCColor(src, (src->bitmap[1][bmoffs] >> v) & 3, 0, src->laceBank2, scroffs); + } + else + { + c = dmC64GetMCColor(src, (src->bitmap[0][bmoffs] >> v) & 3, 0, 0, scroffs); + *d++ = c; + if (doubleMC) + *d++ = c; + } + } + } + dp += dst->pitch; + } + + return DMERR_OK; +} + + +int dmC64ConvertBMP2Image(DMImage **pdst, const DMC64Image *src, const DMC64ImageFormat *fmt, const BOOL doubleMC) +{ + int width, res; + DMImage *dst; + + if (pdst == NULL || src == NULL) + return DMERR_NULLPTR; + + // Calculate output image width + if ((src->type & D64_FMT_MC) && !doubleMC) + width = C64_SCR_WIDTH / 2; + else + width = C64_SCR_WIDTH; + + // Allocate image structure + if ((*pdst = dst = dmImageAlloc(width, C64_SCR_HEIGHT)) == NULL) + return DMERR_MALLOC; + + // Set palette + dst->pal = (DMColor *) &dmC64Palette; + dst->ncolors = C64_NCOLORS; + dst->constpal = TRUE; + + // Convert + if (fmt->convertFrom != NULL) + res = fmt->convertFrom(dst, src, doubleMC); + else + res = dmC64ConvertGenericBMP2Image(dst, src, doubleMC); + + return res; +} + + +int dmC64DecodeBMP(DMC64Image *img, const Uint8 *buf, const size_t len, + const size_t probeOffs, const size_t loadOffs, + const DMC64ImageFormat **fmt, const DMC64ImageFormat *forced) +{ + // Check for forced format + if (forced != NULL) + *fmt = forced; + else + { + // Nope, perform a generic probe + if (probeOffs >= len) + return -200; + + if (dmC64ProbeBMP(buf + probeOffs, len - probeOffs, fmt) == DM_PROBE_SCORE_FALSE) + return -201; + } + + if (loadOffs >= len) + return -203; + + // Decode the bitmap to memory layout + if ((*fmt)->decode != NULL) + return (*fmt)->decode(img, buf + loadOffs, len - loadOffs, *fmt); + else + return dmC64DecodeGenericBMP(img, buf + loadOffs, len - loadOffs, *fmt); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/lib64gfx.h Tue Feb 24 00:47:39 2015 +0200 @@ -0,0 +1,195 @@ +/* + * Functions for reading and converting various restricted + * C64/etc and/or indexed/paletted graphics formats. + * Programmed and designed by Matti 'ccr' Hamalainen + * (C) Copyright 2012 Tecnic Software productions (TNSP) + * + * Please read file 'COPYING' for information on license and distribution. + */ +#ifndef LIB64GFX_H +#define LIB64GFX_H 1 + +#include "libgfx.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +// Bitmap constants +#define C64_SCR_WIDTH 320 +#define C64_SCR_HEIGHT 200 +#define C64_SCR_CH_WIDTH (C64_SCR_WIDTH/8) +#define C64_SCR_CH_HEIGHT (C64_SCR_HEIGHT/8) +#define C64_SCR_COLOR_SIZE (C64_SCR_CH_WIDTH * C64_SCR_CH_HEIGHT) +#define C64_SCR_SCREEN_SIZE (C64_SCR_CH_WIDTH * C64_SCR_CH_HEIGHT) +#define C64_SCR_BITMAP_SIZE (C64_SCR_WIDTH * C64_SCR_HEIGHT/8) +#define C64_SCR_EXTRADATA 1024 +#define C64_SCR_MAX_BANK 8 + +// C64 video screen pixel aspect ratio on PAL +#define C64_SCR_PAR_XY (0.9365f) + +// Sprite constants +#define C64_SPR_WIDTH 3 // bytes +#define C64_SPR_HEIGHT 21 // lines +#define C64_SPR_WIDTH_PX (8 * C64_SPR_WIDTH) +#define C64_SPR_SIZE ((C64_SPR_WIDTH * C64_SPR_HEIGHT) + 1) + +// Character constants +#define C64_CHR_WIDTH 1 // bytes +#define C64_CHR_HEIGHT 8 // lines +#define C64_CHR_WIDTH_PX (8 * C64_CHR_WIDTH) +#define C64_CHR_SIZE (C64_CHR_WIDTH * C64_CHR_HEIGHT) + +// Etc. +#define C64_RAM_SIZE (64*1024) +#define C64_NCOLORS 16 +#define C64_MAX_COLORS 16 +#define C64_VIDBANK_SIZE (16*1024) +#define C64_MAX_SPRITES (C64_VIDBANK_SIZE / C64_SPR_SIZE) +#define C64_MAX_CHARS 256 + +// Different supported C64 bitmap "modes" +enum +{ + D64_FMT_HIRES = 0x0000, + D64_FMT_MC = 0x0001, + D64_FMT_ILACE = 0x0002, + D64_FMT_FLI = 0x0004, + + D64_FMT_MODE_MASK = 0x000f, + +}; + +enum +{ + D64_FLI_2BANK, + D64_FLI_4BANK, + D64_FLI_8BANK, +}; + +enum +{ + D64_ILACE_COLOR, + D64_ILACE_RES, +}; + +typedef struct +{ + BOOL multicolor, xexpand, yexpand; + int color, xc, yc; + Uint8 data[C64_SPR_HEIGHT][C64_SPR_WIDTH]; +} DMC64Sprite; + +enum +{ + D64_CHR_GLOBAL, // use font-global setting + D64_CHR_MULTICOLOR, // character is multicolor + D64_CHR_HIRES, +}; + +typedef struct +{ + int mode, color; + Uint8 data[C64_CHR_HEIGHT]; +} DMC64Char; + + +typedef struct +{ + BOOL multicolor; + int colbg, color, col1, col2; + int nglyphs; + DMC64Char *glyphs; +} DMC64Font; + + + +typedef struct +{ + int type, // Image type (D64_FMT_*) + fliType, // FLI type (if FLI used) + laceType, // Interlace type (D64_ILACE_*) + laceBank1, + laceBank2; + + Uint8 color[C64_SCR_MAX_BANK][C64_SCR_COLOR_SIZE], + bitmap[C64_SCR_MAX_BANK][C64_SCR_BITMAP_SIZE], + screen[C64_SCR_MAX_BANK][C64_SCR_SCREEN_SIZE], + extradata[C64_SCR_EXTRADATA], + d020, bgcolor, d022, d023, d024; + + Uint8 charset[C64_MAX_CHARS][C64_CHR_HEIGHT * C64_CHR_WIDTH]; + DMC64Sprite sprites[C64_MAX_SPRITES]; +} DMC64Image; + + +enum +{ + DT_COLOR_RAM, + DT_BITMAP, + DT_SCREEN_RAM, + DT_BGCOLOR, + DT_BGCOLOR_SET, + DT_EXTRADATA, + + DT_DEC_FUNCTION, + DT_ENC_FUNCTION, + + DT_LAST, +}; + + +typedef struct _DMC64EncDecOp +{ + int type; + size_t offs; + int bank; + size_t size; + BOOL (*decfunction)(DMC64Image *img, const struct _DMC64EncDecOp *op, const Uint8 *buf, const size_t len); + BOOL (*encfunction)(const struct _DMC64EncDecOp *op, Uint8 **buf, size_t *len, const DMC64Image *img); +} DMC64EncDecOp; + + +typedef struct _DMC64ImageFormat +{ + int type; + char *fext; + char *name; + size_t addr; // Loading address (0 if no loading address) + size_t size; // Size, including loading address. Only used in encoding, if even there (0 if no static size) + int (*probe)(const Uint8 *buf, const size_t len, const struct _DMC64ImageFormat *fmt); + int (*decode)(DMC64Image *img, const Uint8 *buf, const size_t len, const struct _DMC64ImageFormat *fmt); + int (*encode)(DMC64Image *img, Uint8 **buf, size_t *len, const struct _DMC64ImageFormat *fmt); + int (*convertFrom)(DMImage *, const DMC64Image *, const BOOL doubleMC); + int (*convertTo)(DMImage *, DMC64Image *); + + int nencdecOps; + DMC64EncDecOp encdecOps[16]; +} DMC64ImageFormat; + + +extern const size_t dmC64DefaultSizes[DT_LAST]; +extern DMColor dmC64Palette[C64_NCOLORS]; +extern const DMC64ImageFormat dmC64ImageFormats[]; +extern const int ndmC64ImageFormats; + + +char * dmC64GetImageTypeString(char *buf, const size_t len, const int type); +int dmC64ConvertCSDataToImage(DMImage *img, int xoffs, int yoffs, const Uint8 *inBuf, int width, int height, BOOL multicolor, int *colors); + +int dmC64DecodeGenericBMP(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt); +int dmC64EncodeGenericBMP(Uint8 **pbuf, size_t *plen, const DMC64Image *img, const DMC64ImageFormat *fmt); +int dmC64ConvertGenericBMP2Image(DMImage *dst, const DMC64Image *src, const BOOL doubleMC); + +int dmC64ConvertBMP2Image(DMImage **pdst, const DMC64Image *src, const DMC64ImageFormat *fmt, const BOOL doubleMC); +int dmC64ProbeBMP(const Uint8 *buf, const size_t len, const DMC64ImageFormat **fmt); +int dmC64DecodeBMP(DMC64Image *img, const Uint8 *buf, const size_t len, const size_t probeOffs, const size_t loadOffs, const DMC64ImageFormat **fmt, const DMC64ImageFormat *forced); + + +#ifdef __cplusplus +} +#endif + +#endif // LIB64GFX_H