changeset 1375:f5368c13a872

Implement more flexible generic format decoding by separating the pixel decoding functions into function pointers.
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 24 Sep 2017 16:01:17 +0300
parents 9edb17aa4a0a
children 67ae449cf9e1
files tools/lib64gfx.c tools/lib64gfx.h tools/view64.c
diffstat 3 files changed, 88 insertions(+), 59 deletions(-) [+]
line wrap: on
line diff
--- a/tools/lib64gfx.c	Sun Sep 24 15:22:45 2017 +0300
+++ b/tools/lib64gfx.c	Sun Sep 24 16:01:17 2017 +0300
@@ -374,7 +374,7 @@
         C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
         C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
         fmtProbeDrazPaint20Packed, fmtDecodeDrazPaintPacked,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_COLOR_RAM,    0x0000, 0,  0, NULL, NULL },
             { DT_BITMAP,       0x0800, 0,  0, NULL, NULL },
@@ -389,7 +389,7 @@
         C64_SCR_WIDTH   , C64_SCR_HEIGHT,
         C64_SCR_CH_WIDTH, C64_SCR_CH_HEIGHT,
         fmtProbeDrazLace10Packed, fmtDecodeDrazPaintPacked,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_COLOR_RAM,    0x0000, 0,  0, NULL, NULL },
             { DT_BITMAP,       0x0800, 0,  0, NULL, NULL },
@@ -406,7 +406,7 @@
         C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
         C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
         NULL, NULL,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_COLOR_RAM,    0x0000, 0,  0, NULL, NULL },
             { DT_BITMAP,       0x0800, 0,  0, NULL, NULL },
@@ -421,7 +421,7 @@
         C64_SCR_WIDTH   , C64_SCR_HEIGHT,
         C64_SCR_CH_WIDTH, C64_SCR_CH_HEIGHT,
         NULL, NULL,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_COLOR_RAM,    0x0000, 0,  0, NULL, NULL },
             { DT_BITMAP,       0x0800, 0,  0, NULL, NULL },
@@ -438,7 +438,7 @@
         C64_SCR_WIDTH   , C64_SCR_HEIGHT,
         C64_SCR_CH_WIDTH, C64_SCR_CH_HEIGHT,
         NULL, NULL,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_SCREEN_RAM,   0x0000, 0,  0, NULL, NULL },
             { DT_COLOR_REG,    0x03e8, 0,  DC_BGCOL, NULL, NULL },
@@ -456,7 +456,7 @@
         C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
         C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
         NULL, NULL,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_BITMAP,       0x0000, 0,  0, NULL, NULL },
             { DT_SCREEN_RAM,   0x1f40, 0,  0, NULL, NULL },
@@ -471,7 +471,7 @@
         C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
         C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
         NULL, NULL,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_BITMAP,       0x0000, 0,  0, NULL, NULL },
             { DT_SCREEN_RAM,   0x1f40, 0,  0, NULL, NULL },
@@ -486,7 +486,7 @@
         C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
         C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
         fmtProbeAmicaPaintPacked, fmtDecodeAmicaPaintPacked,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_COLOR_RAM,    0x2328, 0,  0, NULL, NULL },
             { DT_BITMAP,       0x0000, 0,  0, NULL, NULL },
@@ -501,7 +501,7 @@
         C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
         C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
         NULL, NULL,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_COLOR_RAM,    0x2328, 0,  0, NULL, NULL },
             { DT_BITMAP,       0x0000, 0,  0, NULL, NULL },
@@ -516,7 +516,7 @@
         C64_SCR_WIDTH    , C64_SCR_HEIGHT,
         C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
         NULL, NULL,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_BITMAP,       0x0000, 0,  0, NULL, NULL },
             { DT_SCREEN_RAM,   0x1f40, 0,  0, NULL, NULL },
@@ -529,7 +529,7 @@
         C64_SCR_WIDTH   , C64_SCR_HEIGHT,
         C64_SCR_CH_WIDTH, C64_SCR_CH_HEIGHT,
         NULL, NULL,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_BITMAP,       0x0000, 0,  0, NULL, NULL },
             { DT_SCREEN_RAM,   0x1f40, 0,  0, NULL, NULL },
@@ -541,7 +541,7 @@
         C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
         C64_SCR_CH_WIDTH, C64_SCR_CH_HEIGHT,
         NULL, NULL,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_BITMAP,       0x0000, 0,  0, NULL, NULL },
             { DT_SCREEN_RAM,   0x1f40, 0,  0, NULL, NULL },
@@ -556,7 +556,7 @@
         C64_SCR_WIDTH   , C64_SCR_HEIGHT,
         C64_SCR_CH_WIDTH, C64_SCR_CH_HEIGHT,
         NULL, NULL,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_SCREEN_RAM,   0x0000, 0,  0, NULL, NULL },
             { DT_BITMAP,       0x0400, 0,  0, NULL, NULL },
@@ -569,7 +569,7 @@
         C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
         C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
         NULL, NULL,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_COLOR_RAM,    0x0100, 0,  0, NULL, NULL },
 
@@ -594,7 +594,7 @@
         C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
         C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
         NULL, NULL,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_COLOR_RAM,    0x0000, 0,  0, NULL, NULL },
             { DT_SCREEN_RAM,   0x0400, 0,  0, NULL, NULL },
@@ -616,7 +616,7 @@
         C64_SCR_WIDTH / 2, C64_SCR_HEIGHT,
         C64_SCR_CH_WIDTH , C64_SCR_CH_HEIGHT,
         NULL, NULL,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_BITMAP,       0x0000, 0,  0, NULL, NULL },
             { DT_SCREEN_RAM,   0x2000, 0,  0, NULL, NULL },
@@ -636,7 +636,7 @@
         XX2_WIDTH_CH * 4, XX2_HEIGHT_CH * 8,
         XX2_WIDTH_CH    , XX2_HEIGHT_CH,
         fmtProbeFormatXX2, fmtDecodeFormatXX2,
-        NULL, NULL, NULL,
+        NULL, NULL, NULL, NULL,
         {
             { DT_BITMAP,       0x0000, 0,  XX2_BSIZE, NULL, NULL },
             { DT_COLOR_RAM,    XX2_BSIZE + XX2_SIZE, 0,  XX2_SIZE, NULL, NULL },
@@ -1080,9 +1080,24 @@
 }
 
 
-static inline Uint8 dmC64GetMCColor(const DMC64Image *img,
-    const int bits, const int cbank, const int vbank, const int scroffs)
+static inline Uint8 dmC64GetSCPixel(
+    const DMC64Image *img, const int bmoffs, const int vshift,
+    const int vbank, const int scroffs, const int raster)
 {
+    (void) raster;
+    if ((img->bitmap[vbank][bmoffs] >> vshift) & 1)
+        return img->screen[vbank][scroffs] >> 4;
+    else
+        return img->screen[vbank][scroffs] & 15;
+}
+
+
+static inline Uint8 dmC64GetMCColor(
+    const DMC64Image *img,
+    const int bits, const int cbank, const int vbank,
+    const int scroffs, const int raster)
+{
+    (void) raster;
     switch (bits)
     {
         case  0: return img->bgcolor; break;
@@ -1093,12 +1108,40 @@
 }
 
 
+static inline Uint8 dmC64GetMCPixel(
+    const DMC64Image *img, const int bmoffs, const int vshift,
+    const int vbank, const int scroffs, const int raster)
+{
+    if (img->type & D64_FMT_FLI)
+    {
+        const int yb = raster & 7;
+        int vbank = 0;
+        switch (img->fliType)
+        {
+            case D64_FLI_2BANK:
+                vbank = yb / 4;
+                break;
+            case D64_FLI_4BANK:
+                vbank = yb / 2;
+                break;
+            case D64_FLI_8BANK:
+                vbank = yb;
+                break;
+        }
+        return dmC64GetMCColor(img, (img->bitmap[0][bmoffs] >> vshift) & 3, 0, vbank, scroffs, raster);
+    }
+    else
+        return dmC64GetMCColor(img, (img->bitmap[0][bmoffs] >> vshift) & 3, 0, vbank, scroffs, raster);
+}
+
+
 // Convert a generic "C64" format bitmap in DMC64Image struct to
 // a indexed/paletted bitmap image.
-int dmC64ConvertGenericBMP2Image(DMImage *dst, const DMC64Image *src)
+int dmC64ConvertGenericBMP2Image(DMImage *dst, const DMC64Image *src, const DMC64ImageFormat *fmt)
 {
     Uint8 *dp = dst->data;
     int yc;
+    DMC64GetPixelFunc getPixel;
 
     // Sanity check arguments
     if (dst == NULL || src == NULL)
@@ -1109,6 +1152,12 @@
 
     dmMemset(dst->data, 0, dst->size);
 
+    // Check pixel getter function
+    if (fmt->getPixel != NULL)
+        getPixel = fmt->getPixel;
+    else
+        getPixel = (fmt->type & D64_FMT_MC) ? dmC64GetMCPixel : dmC64GetSCPixel;
+
     // Resolution interlaced pics need to halve the source width
     int rwidth = src->width;
     if ((src->type & D64_FMT_ILACE) && src->laceType == D64_ILACE_RES)
@@ -1181,12 +1230,9 @@
                 const int x = xc / 8;
                 const int scroffs = scroffsy + x;
                 const int bmoffs = bmoffsy + (x * 8);
-                const int v = 7 - (xc & 7);
+                const int vshift = 7 - (xc & 7);
 
-                if ((src->bitmap[0][bmoffs] >> v) & 1)
-                    *d++ = src->screen[0][scroffs] >> 4;
-                else
-                    *d++ = src->screen[0][scroffs] & 15;
+                *d++ = getPixel(src, bmoffs, vshift, 0, scroffs, yc);
             }
             else
             // Multicolor bitmap and variants
@@ -1195,35 +1241,15 @@
                 const int x = xc / 4;
                 const int scroffs = scroffsy + x;
                 const int bmoffs = bmoffsy + (x * 8);
-                const int v = 6 - ((xc * 2) & 6);
-                Uint8 c;
+                const int vshift = 6 - ((xc * 2) & 6);
 
-                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;
-                }
-                else
                 if (src->type & D64_FMT_ILACE)
                 {
                     switch (src->laceType)
                     {
                         case D64_ILACE_RES:
-                            *d++ = dmC64GetMCColor(src, (src->bitmap[0][bmoffs] >> v) & 3, 0, src->laceBank1, scroffs);
-                            *d++ = dmC64GetMCColor(src, (src->bitmap[1][bmoffs] >> v) & 3, 0, src->laceBank2, scroffs);
+                            *d++ = getPixel(src, bmoffs, vshift, src->laceBank1, scroffs, yc);
+                            *d++ = getPixel(src, bmoffs, vshift, src->laceBank2, scroffs, yc);
                             break;
 
                         default:
@@ -1232,8 +1258,7 @@
                 }
                 else
                 {
-                    c = dmC64GetMCColor(src, (src->bitmap[0][bmoffs] >> v) & 3, 0, 0, scroffs);
-                    *d++ = c;
+                    *d++ = getPixel(src, bmoffs, vshift, 0, scroffs, yc);
                 }
             }
         }
@@ -1263,9 +1288,9 @@
 
     // Convert
     if (fmt->convertFrom != NULL)
-        res = fmt->convertFrom(dst, src);
+        res = fmt->convertFrom(dst, src, fmt);
     else
-        res = dmC64ConvertGenericBMP2Image(dst, src);
+        res = dmC64ConvertGenericBMP2Image(dst, src, fmt);
 
     return res;
 }
--- a/tools/lib64gfx.h	Sun Sep 24 15:22:45 2017 +0300
+++ b/tools/lib64gfx.h	Sun Sep 24 16:01:17 2017 +0300
@@ -107,8 +107,6 @@
 };
 
 
-typedef struct _DMC64Image DMC64Image;
-
 typedef struct _DMC64Image
 {
     int type,       // Image type (D64_FMT_*)
@@ -133,6 +131,11 @@
 } DMC64Image;
 
 
+typedef Uint8 (*DMC64GetPixelFunc)(
+    const DMC64Image *img,
+    const int bits, const int cbank, const int vbank,
+    const int scroffs, const int raster);
+
 enum
 {
     DT_COLOR_RAM,
@@ -180,8 +183,9 @@
     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 *);
-    int  (*convertTo)(DMImage *, DMC64Image *);
+    int  (*convertFrom)(DMImage *, const DMC64Image *, const struct _DMC64ImageFormat *fmt);
+    int  (*convertTo)(DMImage *, DMC64Image *, const struct _DMC64ImageFormat *fmt);
+    DMC64GetPixelFunc getPixel;
 
     DMC64EncDecOp encdecOps[D64_MAX_ENCDEC_OPS];
 } DMC64ImageFormat;
@@ -201,7 +205,7 @@
 
 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);
+int       dmC64ConvertGenericBMP2Image(DMImage *dst, const DMC64Image *src, const DMC64ImageFormat *fmt);
 
 int       dmC64ConvertBMP2Image(DMImage **pdst, const DMC64Image *src, const DMC64ImageFormat *fmt);
 int       dmC64ProbeBMP(const Uint8 *buf, const size_t len, const DMC64ImageFormat **fmt);
--- a/tools/view64.c	Sun Sep 24 15:22:45 2017 +0300
+++ b/tools/view64.c	Sun Sep 24 16:01:17 2017 +0300
@@ -302,9 +302,9 @@
     bmap.constpal = TRUE;
 
     if (fmt->convertFrom != NULL)
-        ret = fmt->convertFrom(&bmap, cimage);
+        ret = fmt->convertFrom(&bmap, cimage, fmt);
     else
-        ret = dmC64ConvertGenericBMP2Image(&bmap, cimage);
+        ret = dmC64ConvertGenericBMP2Image(&bmap, cimage, fmt);
 
 
     // Set window title and caption