# HG changeset patch # User Matti Hamalainen # Date 1525976844 -10800 # Node ID bde6a66bc2f6da6290f9e2018bfe8db94de8d880 # Parent 9cb6dd1046bfb3ef1ccab217c010abe32bc8e51d Change dmDecodeGenericRLE() to use DMGrowBuf as output. Also add support for two different common types of RLE encoding. Add stub function of dmEncodeGenericRLE(), not implemented yet. Change functions using dmDecodeGenericRLE to use the new API. Also fix a problem in Amica Paint RLE decoding as the format seems to save one byte less than is necessary. diff -r 9cb6dd1046bf -r bde6a66bc2f6 tools/lib64gfx.c --- a/tools/lib64gfx.c Thu May 10 21:22:31 2018 +0300 +++ b/tools/lib64gfx.c Thu May 10 21:27:24 2018 +0300 @@ -33,6 +33,9 @@ { 0x95, 0x95, 0x95, 0xff }, }; +#define DM_RLE_MARKER 1 +#define DM_RLE_MASK 2 + #define DM_GET_ADDR_LO(addr) ((addr) & 0xff) #define DM_GET_ADDR_HI(addr) (((addr) >> 8) & 0xff) @@ -222,32 +225,79 @@ } -static int dmDecodeGenericRLE(Uint8 **mem, Uint8 **pdstEnd, const Uint8 *src, const Uint8 *srcEnd, const Uint8 rleMarker) +static int dmDecodeGenericRLE(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd, const Uint8 rleMarker, const Uint8 rleMask, const int rleType) { - Uint8 *dst, *dstEnd; + int res; - if ((*mem = dmMalloc(C64_RAM_SIZE)) == NULL) - return DMERR_MALLOC; + if ((res = dmGrowBufAlloc(dst, BUF_SIZE_INITIAL, BUF_SIZE_GROW)) != DMERR_OK) + goto err; - dst = *mem; - dstEnd = *mem + C64_RAM_SIZE; - - while (src <= srcEnd && dst <= dstEnd) + // Perform RLE decode + while (src < srcEnd) { Uint8 c = *src++; - if (c == rleMarker && src + 2 <= srcEnd) + int cnt = 1; + + switch (rleType) { - int cnt = *src++; - c = *src++; - while (cnt-- && dst <= dstEnd) - *dst++ = c; + case DM_RLE_MARKER: + if (c == rleMarker) + { + if (srcEnd - src < 2) + { + res = dmError(DMERR_INVALID_DATA, + "Foobar: %d\n", srcEnd - src); + goto err; + } + cnt = *src++; + c = *src++; + } + break; + + case DM_RLE_MASK: + if ((c & rleMask) == rleMarker) + { + if (srcEnd - src < 1) + { + res = dmError(DMERR_INVALID_DATA, + "foobar2\n"); + goto err; + } + // XXX TODO actually we probably want another mask here + cnt = c & (0xff ^ rleMask); + c = *src++; + } + break; } - else - *dst++ = c; + + while (cnt--) + { + if (!dmGrowBufPutU8(dst, c)) + { + res = dmError(DMERR_MALLOC, + "bazzooo\n"); + goto err; + } + } } - *pdstEnd = dst; + // Reallocate the memory + if ((res = dmGrowBufResize(dst)) != DMERR_OK) + goto err; + + res = DMERR_OK; +err: + return res; +} + + +static int dmEncodeGenericRLE(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd, const Uint8 rleMarker) +{ + (void) dst; + (void) src; + (void) srcEnd; + (void) rleMarker; return DMERR_OK; } @@ -316,15 +366,15 @@ static int fmtDecodeDrazPaintPacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) { int res; - Uint8 *mem = NULL, *end; + DMGrowBuf mem; - if ((res = dmDecodeGenericRLE(&mem, &end, buf + 0x0e, buf + len - 1, *(buf + 0x0d))) != DMERR_OK) + if ((res = dmDecodeGenericRLE(&mem, buf + 0x0e, buf + len, *(buf + 0x0d), 0, DM_RLE_MARKER)) != DMERR_OK) goto out; - res = dmC64DecodeGenericBMP(img, mem, end - mem + 1, fmt); + res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt); out: - dmFree(mem); + dmGrowBufFree(&mem); return res; } @@ -388,15 +438,27 @@ static int fmtDecodeAmicaPaintPacked(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) { int res; - Uint8 *mem = NULL, *end; + DMGrowBuf mem, tmp; + + // Amica Paint apparently is broken and stores one byte less than it should + // so we need to do some crappy buffer expansion here .. + if ((res = dmGrowBufAlloc(&tmp, len + 4, 4)) != DMERR_OK) + return res; - if ((res = dmDecodeGenericRLE(&mem, &end, buf, buf + len - 1, 0xC2)) != DMERR_OK) + tmp.len = len; + memcpy(tmp.data, buf, len); + tmp.data[tmp.len++] = 0; + + // Now do an RLE decode on the enlarged buffer + if ((res = dmDecodeGenericRLE(&mem, tmp.data, tmp.data + tmp.len, 0xC2, 0, DM_RLE_MARKER)) != DMERR_OK) goto out; - res = dmC64DecodeGenericBMP(img, mem, end - mem + 1, fmt); + // And finally decode to bitmap struct + res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt); out: - dmFree(mem); + dmGrowBufFree(&tmp); + dmGrowBufFree(&mem); return res; } @@ -502,15 +564,16 @@ static int fmtDecodeFunPaint2Packed(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt) { int res; - Uint8 *mem = NULL, *end; + DMGrowBuf mem; + dmGrowBufInit(&mem); - if ((res = dmDecodeGenericRLE(&mem, &end, buf + FUNPAINT2_HEADER_SIZE, buf + len - 1, *(buf + 15))) != DMERR_OK) + if ((res = dmDecodeGenericRLE(&mem, buf + FUNPAINT2_HEADER_SIZE, buf + len, *(buf + 15), 0, DM_RLE_MARKER)) != DMERR_OK) goto out; - res = dmC64DecodeGenericBMP(img, mem, end - mem + 1, fmt); + res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt); out: - dmFree(mem); + dmGrowBufFree(&mem); return res; }