# HG changeset patch # User Matti Hamalainen # Date 1558945699 -10800 # Node ID a8f5295ab2e70bb81d96ef172101c12674dbd3fa # Parent c1a9519a619ff4b63257de71611e3ab6ca48fb3f Validate format index values better in dmC64GetImageTypeString(). diff -r c1a9519a619f -r a8f5295ab2e7 tools/lib64gfx.c --- 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; } }