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