changeset 2128:a8f5295ab2e7

Validate format index values better in dmC64GetImageTypeString().
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 27 May 2019 11:28:19 +0300
parents c1a9519a619f
children 2129d4ac6f45
files tools/lib64gfx.c
diffstat 1 files changed, 146 insertions(+), 147 deletions(-) [+]
line wrap: on
line diff
--- a/tools/lib64gfx.c	Mon May 27 11:12:21 2019 +0300
+++ b/tools/lib64gfx.c	Mon May 27 11:28:19 2019 +0300
@@ -38,10 +38,14 @@
 {
     static const char *fmtModesShort[] = { "ERROR", "HiR", "MC", "ECM" };
     static const char *fmtModesLong[] = { "ERROR", "HiRes", "MultiColor", "Extended Color Mode" };
+    size_t nfmt = type & D64_FMT_MASK;
+
+    if (nfmt >= sizeof(fmtModesShort) / sizeof(fmtModesShort[0]))
+        nfmt = 0;
 
     snprintf(buf, len,
         "%s %s%s%s",
-        lng ? fmtModesLong[type & D64_FMT_MASK] : fmtModesShort[type & D64_FMT_MASK],
+        lng ? fmtModesLong[nfmt] : fmtModesShort[nfmt],
         (type & D64_FMT_ILACE) ? (lng ? "Interlaced " : "ILace ") : "",
         (type & D64_FMT_FLI)   ? "FLI " : "",
         (type & D64_FMT_CHAR)  ? "CHAR" : ""
@@ -1258,6 +1262,127 @@
 }
 
 
+static int fmtGetGenericSCPixel(Uint8 *col,
+    const DMC64Image *img, const int rasterX, const int rasterY)
+{
+    DM_C64_GENERIC_SC_PIXEL_DEFS(img)
+
+    return dmC64GetGenericSCPixel(
+        col, img, bmoffs, scroffs, vshift, 0, 0);
+}
+
+
+static int fmtGetGenericMCPixel(Uint8 *col,
+    const DMC64Image *img, const int rasterX, const int rasterY)
+{
+    DM_C64_GENERIC_MC_PIXEL_DEFS(img)
+
+    return dmC64GetGenericMCPixel(
+        col, img, bmoffs, scroffs, vshift, 0, 0, 0, img->bgcolor);
+}
+
+
+static int fmtGetGenericCharSCPixel(Uint8 *col,
+    const DMC64Image *img, const int rasterX, const int rasterY)
+{
+    const int
+        x = rasterX / 8,
+        y = rasterY / 8,
+        scroffs = y * img->fmt->chWidth + x,
+        vshift = 7 - (rasterX & 7),
+        chr = img->screen[0].data[scroffs];
+
+    const size_t chroffs = (chr * D64_CHR_SIZE) + (rasterY & 7);
+    if (chroffs >= img->charData[0].size)
+    {
+        return dmError(DMERR_INVALID_DATA,
+            "Character map index #%d out of bounds for char ROM data.\n",
+            chr);
+    }
+
+    if ((img->charData[0].data[chroffs] >> vshift) & 1)
+        *col = img->color[0].data[scroffs];
+    else
+        *col = img->bgcolor;
+
+    return DMERR_OK;
+}
+
+
+static int fmtGetGenericCharMCPixel(Uint8 *col,
+    const DMC64Image *img, const int rasterX, const int rasterY)
+{
+    const int
+        y = rasterY / 8,
+        scroffs = y * img->fmt->chWidth + (rasterX / 8),
+        chr = img->screen[0].data[scroffs],
+        ccol = img->color[0].data[scroffs];
+
+    const size_t chroffs = (chr * D64_CHR_SIZE) + (rasterY & 7);
+    if (chroffs >= img->charData[0].size)
+    {
+        return dmError(DMERR_INVALID_DATA,
+            "Character map index #%d out of bounds for char ROM data.\n",
+            chr);
+    }
+
+    if (ccol & 8)
+    {
+        const int vshift = 6 - (rasterX & 6);
+        switch ((img->charData[0].data[chroffs] >> vshift) & 3)
+        {
+            case 0: *col = img->bgcolor; break;
+            case 1: *col = img->d022; break;
+            case 2: *col = img->d023; break;
+            case 3: *col = ccol & 15;
+        }
+    }
+    else
+    {
+        const int vshift = 7 - (rasterX & 7);
+        if ((img->charData[0].data[chroffs] >> vshift) & 1)
+            *col = ccol & 7;
+        else
+            *col = img->bgcolor;
+    }
+
+    return DMERR_OK;
+}
+
+
+static int fmtGetGenericCharECMPixel(Uint8 *col,
+    const DMC64Image *img, const int rasterX, const int rasterY)
+{
+    const int
+        x = rasterX / 8,
+        y = rasterY / 8,
+        scroffs = y * img->fmt->chWidth + x,
+        vshift = 7 - (rasterX & 7),
+        chr = img->screen[0].data[scroffs];
+
+    const size_t chroffs = ((chr & 0x3f) * D64_CHR_SIZE) + (rasterY & 7);
+    if (chroffs >= img->charData[0].size)
+    {
+        return dmError(DMERR_INVALID_DATA,
+            "Character map index #%d out of bounds for char ROM data.\n",
+            chr);
+    }
+
+    if ((img->charData[0].data[chroffs] >> vshift) & 1)
+        *col = img->color[0].data[scroffs] & 15;
+    else
+    switch ((chr >> 6) & 3)
+    {
+        case 0: *col = img->bgcolor; break;
+        case 1: *col = img->d022; break;
+        case 2: *col = img->d023; break;
+        case 3: *col = img->d024; break;
+    }
+
+    return DMERR_OK;
+}
+
+
 // Convert a generic "C64" format bitmap in DMC64Image struct to
 // a indexed/paletted bitmap image.
 int dmC64ConvertGenericBMP2Image(DMImage *dst, const DMC64Image *src,
@@ -1282,163 +1407,37 @@
     if (src->fmt->getPixel != NULL)
         getPixel = src->fmt->getPixel;
     else
+    if (src->fmt->type & D64_FMT_CHAR)
     switch (src->fmt->type & D64_FMT_MASK)
     {
-        case D64_FMT_MC: getPixel = fmtGetGenericMCPixel; break;
-        case D64_FMT_HIRES: getPixel = fmtGetGenericSCPixel; break;
+        case D64_FMT_MC    : getPixel = fmtGetGenericCharMCPixel; break;
+        case D64_FMT_HIRES : getPixel = fmtGetGenericCharSCPixel; break;
+        case D64_FMT_ECM   : getPixel = fmtGetGenericCharECMPixel; break;
         default:
             return dmError(DMERR_INVALID_DATA,
-                "Invalid bitmap image type/fmt=%d.\n",
+                "Invalid character map image type/fmt=0x%x.\n",
+                src->fmt->type);
+    }
+    else
+    switch (src->fmt->type & D64_FMT_MASK)
+    {
+        case D64_FMT_MC    : getPixel = fmtGetGenericMCPixel; break;
+        case D64_FMT_HIRES : getPixel = fmtGetGenericSCPixel; break;
+        default:
+            return dmError(DMERR_INVALID_DATA,
+                "Invalid bitmap image type/fmt=0x%x.\n",
                 src->fmt->type);
     }
 
-    // Resolution interlaced pics need to halve the source width
-    int rwidth = dst->width, rheight = dst->height;
-    if ((src->fmt->type & D64_FMT_ILACE) &&
-        src->laceType == D64_ILACE_RES)
-        rwidth /= 2;
-
     // Perform conversion
-    for (int yc = 0; yc < rheight; yc++)
+    for (int yc = 0; yc < dst->height; yc++)
     {
         Uint8 *dp = dst->data + (yc * dst->pitch);
-        const int y = yc / 8, yb = yc & 7;
-        const int scroffsy = y * src->fmt->chWidth;
-        const int bmoffsy = y * src->fmt->chWidth * 8 + yb;
-
-        for (int xc = 0; xc < rwidth; xc++)
-        if (src->fmt->type & D64_FMT_CHAR)
+        for (int xc = 0; xc < dst->width; xc++, dp++)
         {
-            // Charmode conversion
-            if ((src->fmt->type & D64_FMT_MASK) == D64_FMT_HIRES)
-            {
-                // Hi-res charmap
-                const int x = xc / 8;
-                const int scroffs = scroffsy + x;
-                const int xshift = 7 - (xc & 7);
-                const int chr = src->screen[0].data[scroffs];
-                const size_t chrOffs = (chr * D64_CHR_SIZE) + yb;
-
-                if (chrOffs >= src->charData[0].size)
-                {
-                    return dmError(DMERR_INVALID_DATA,
-                        "Character map index #%d out of bounds for char ROM data.\n",
-                        chr);
-                }
-
-                if ((src->charData[0].data[chrOffs] >> xshift) & 1)
-                    *dp++ = src->color[0].data[scroffs];
-                else
-                    *dp++ = src->bgcolor;
-            }
-            else
-            if ((src->fmt->type & D64_FMT_MASK) == D64_FMT_ECM)
-            {
-                // Hi-res ECM charmap
-                const int x = xc / 8;
-                const int scroffs = scroffsy + x;
-                const int xshift = 7 - (xc & 7);
-                const int chr = src->screen[0].data[scroffs];
-                const size_t chrOffs = ((chr & 0x3f) * D64_CHR_SIZE) + yb;
-
-                if (chrOffs >= src->charData[0].size)
-                {
-                    return dmError(DMERR_INVALID_DATA,
-                        "Character map index #%d out of bounds for char ROM data.\n",
-                        chr);
-                }
-
-                if ((src->charData[0].data[chrOffs] >> xshift) & 1)
-                    *dp++ = src->color[0].data[scroffs] & 15;
-                else
-                switch ((chr >> 6) & 3)
-                {
-                    case 0: *dp++ = src->bgcolor; break;
-                    case 1: *dp++ = src->d022; break;
-                    case 2: *dp++ = src->d023; break;
-                    case 3: *dp++ = src->d024; break;
-                }
-            }
-            else
-            if ((src->fmt->type & D64_FMT_MASK) == D64_FMT_MC)
-            {
-                // Multicolor charmap
-                const int x = xc / 4;
-                const int scroffs = scroffsy + x;
-                const int chr = src->screen[0].data[scroffs];
-                const int col = src->color[0].data[scroffs];
-                const size_t chrOffs = (chr * D64_CHR_SIZE) + yb;
-
-                if (chrOffs >= src->charData[0].size)
-                {
-                    return dmError(DMERR_INVALID_DATA,
-                        "Character map index #%d out of bounds for char ROM data.\n",
-                        chr);
-                }
-
-                if (col & 8)
-                {
-                    const int xshift = 6 - ((xc * 2) & 6);
-                    switch ((src->charData[0].data[chrOffs] >> xshift) & 3)
-                    {
-                        case 0: *dp++ = src->bgcolor; break;
-                        case 1: *dp++ = src->d022; break;
-                        case 2: *dp++ = src->d023; break;
-                        case 3: *dp++ = col & 15;
-                    }
-                }
-                else
-                {
-                    const int xshift = 7 - (xc & 7);
-                    if ((src->charData[0].data[chrOffs] >> xshift) & 1)
-                        *dp++ = col & 7;
-                    else
-                        *dp++ = src->bgcolor;
-                }
-            }
-        }
-        else
-        {
-            // Perform generic BITMAP conversion
-            if ((src->fmt->type & D64_FMT_MASK) == D64_FMT_HIRES)
-            {
-                // Hi-res bitmap
-                const int x = xc / 8;
-                const int scroffs = scroffsy + x;
-                const int bmoffs = bmoffsy + (x * 8);
-                const int xshift = 7 - (xc & 7);
-
-                *dp++ = getPixel(src, bmoffs, scroffs, xshift, 0, xc, yc);
-            }
-            else
-            {
-                // Multicolor bitmap and variants
-                const int x = xc / 4;
-                const int scroffs = scroffsy + x;
-                const int bmoffs = bmoffsy + (x * 8);
-                const int xshift = 6 - ((xc * 2) & 6);
-
-                if (src->fmt->type & D64_FMT_ILACE)
-                {
-                    switch (src->laceType)
-                    {
-                        case D64_ILACE_RES:
-                            *dp++ = getPixel(src, bmoffs, scroffs, xshift, 0, xc, yc);
-                            *dp++ = getPixel(src, bmoffs, scroffs, xshift, 1, xc, yc);
-                            break;
-
-                        default:
-                            return DMERR_NOT_SUPPORTED;
-                    }
-                }
-                else
-                {
-                    const Uint8 col = getPixel(src, bmoffs, scroffs, xshift, 0, xc, yc);
-                    *dp++ = col;
-                    if (spec->aspect)
-                        *dp++ = col;
-                }
-            }
+            int res;
+            if ((res = getPixel(dp, src, xc, yc)) != DMERR_OK)
+                return res;
         }
     }